iOS Storyboard Passing Data - ios

Is there anybody who can help a beginner?
I've got two storyboards, the first has a button and the second has a label. I want to push the button and I want the label to display the text.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
second *myVC = segue.destinationViewController;
myVC.mylabel.text = #"Why isn't this working!!";
}
The button acts as the segue.
I would also like to add that I've checked everything and I'm puzzled as to know why it's not working. I would have expect it to work, so if someone could also explain what I'm doing wrong or missing I'd be very grateful.
Thank you for your help.

In prepareForSegue: your second view does not exist yet. The output of mylabel is not connected with the view. Create a new NSString property in your second controller. Set it in prepareForSegue: and use it to setup the label in viewDidLoad: of the second controller.

Related

IOS segue is not working when clicking on an Image

I have a view with an Image View, when the user clicks on it, I want to load the image inside it in a separate view.
This is my segue:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"Show Player Information"]){
if ([segue.destinationViewController isKindOfClass:[PlayerViewController class]]){
PlayerViewController *playerViewController = (PlayerViewController*)segue.destinationViewController;
[playerViewController setPlayer:[self.team.players objectAtIndex:self.tableView.indexPathForSelectedRow.row]];
}
}else if([segue.identifier isEqualToString:#"Show Image"]) {
if ([segue.destinationViewController isKindOfClass:[ImageViewerViewController class]]){
ImageViewerViewController *imageViewerViewController = (ImageViewerViewController*)segue.destinationViewController;
[imageViewerViewController setImageName:#"France.jpg"];
}
}
}
But nothing happens when clicking on the image view though the segue has the correct identifier.
Please check the below screenshot
Could you help me please?
I appreciate your time and efforts.
Regards,
Although it is possible to perform a segue from a UIImageView (although not directly from IB) in my opinion is much simpler to just replace it with a UIButton and set its image instead.
Then, based on your posted code, you could just remove your old segue, ctrl+drag from the button to your destination controller, choose 'push' and then set the segue identifier to Show Image.
It should be noted here that UIImageView (unlike its ancestor UIView) has its userInteractionEnabled property set to NO by default (more about it here). So if you choose to handle any events directly from the UIImageView make sure that you switch it to YES (here is a similar answer regarding this).

Is there a possibility to update the value that was passed by a segue into a second view?

I passed data trough a segue using the prepareForSegue()-method by clicking on a button. Now, I can use it within the second view to print it into a label or something like that. The problem is that the said value changes every few seconds, but the second view only shows the initial value (because the event occurs only one time!). I thought about a timer, but I'm not really sure if this could help me to fix this problem. Does someone know a possibility to realize this kind of updating of data using a segue? If not, how would you like to fix this? I need a hint for a basic approach.
Thanks in advance!
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"tab"]){
NSNumber *sliderNumber = [self.dic objectForKey:#"slider"];
NSString *convertSliderNumber = [sliderNumber stringValue];
TabBarViewController *tabBar = [segue destinationViewController];
[tabBar setLabelString:convertSliderNumber];
}
}
If you create an object that contains that value and give the segued viewController a pointer to that object, then any value you update in that object will be updated in both viewControllers.

iOS/Xcode - Multiple segue identifiers resetting data parsing

So I got a ViewController with 4 seperate buttons. When clicking on button1 TableViewController1 pops over the ViewController with a list of items. When selecting an item the TableViewController1 drops down and button1 now has the text that was selected in the table. This is all good. But when I do the exact same thing for button2 with TableViewController2 the data from button1 is reseted.
I use segues with identifiers, some of the code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showEducation"]) {
NSIndexPath *indexPath = [self.tableViewEducation indexPathForSelectedRow];
ViewController *destViewController = segue.destinationViewController;
destViewController.educationText = [tableViewArray objectAtIndex:indexPath.row];
}
}
So at the moment I got multiple segue identifiers for each button and multiple .h and .m files for the tableviews. Am I using a completely wrong technique to get this to work? I hope im clear enough, otherwise I can upload images.
Edit: I just noticed, I also have a slider on my ViewController. When clicking on a button and selecting a row in the TableView the slider gets reseted to the original position. Same problem as above kind of.
I am thinking that you're pushing to a new instance of your View Controller every time you push from either tableViewController.
Imagine that you click on one button on ViewController0, this creates an instance of tableViewController1. When you click a row, you're just using a performSegue to create a NEW instance of ViewController0, and this has its own ViewDidLoad - resetting the buttons.
(You're saying that the view "drops down", so it's modal?)
Don't use performSegue from the tableViewController back to the viewController, try using [self dismissModalViewController: withCompletion:](or something similar, can't remember), then your tableViewController should remove itself and reveal the original ViewController.
Now, you don't have a way to change the name of the button though, but that can be done by accessing the sender from the tableView, which will give you the original View Controller, and not a new instance of it.
One way of getting the sender is to use [performSegue... from ViewController0, and in it's own prepareForSegue, you could do something like
//In the first ViewController, not in the TableViewControllers
-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender{
if(sender == button1)
{
UITableViewController1 *dest = segue.destinationViewController;
[dest setSender: self];
}
}
And in TableViewController1 you'd create a variable ViewController *home;, and a method -(void)setSender:(ViewController*)sender;, so that in your didSelectRowAtIndexPath, you could now say [[(ViewController0*)home button1]setTitle:#..];, and then [dismissModalViewController..]
There are other ways to do it as well, depending on how you are pushing from your viewController to the tableViewController. And I'm sure there are easier ways to access the sender than this, but it works and is useful if you're already sending other data.

update child view textview in storyboard

I'm working on an app using storyboard and Navigation controller is embedded in. In the child view, when a button is pressed, it calls a function in parent view controller without changing the view.
[self.delegate buttonPressed];
and the method supposed to update the text of textview in child view.
childviewcontroller.textViewName.text=#"something";
But the textview is not being updated.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
[[segue destinationViewController] setDelegate:self];
}
Long story short is, if I want the parent view controller to change the text of a textview in child view controller, how should I set it up when I'm using storyboard.
Can anyone give me some ideas?
I don't know if I explain it clearly or not. I'm still kinda new to this and am learning while making this app. Thank you in advance.
This sounds confusing. If you are needing to fire off a function in the parent VC, why not create a class method that returns what you need and then do something like this in that child VC:
NSString *newText = [MyParentViewController getSomeData];
myTextView.text = newText;
OR even better, put that class method in a new class that gets data for your VC's. This would be more in-line with object oriented programming.

Conditional Segue navigation from UITableViewCell based on response to UIAlertView

My problem seems like a generic problem, yet can't seem to find an answer for it.
I have a situation where when the user taps on a custom UITableViewCell, I would like to display an alert and then based on the response to the alert, either stay on the same view (user selecting cancel) or display another view (if the user selects proceed). And I would like to do this using the storyboard feature & segues.
How would one go about this? Do you have to do this the old fashioned way?
#user, Just create the alertView the old fashion way; I do know of any storyboard feature to do this differently. Where storyboard can help is with the segues. You can call the segues programmatically. With you alert view cancel button you can just return (i.e. do nothing). For the other option, to display another view, you can programmatically call a segue to transition to the desired view. If you don't have the proper segue already defined for some other reason on your storyboard, just create a button out and use that to create the segue and name it. Name the segue by clicking on it in storyboard and use the attributes inspector to give it name (identifier). Then hide the button or put it out of the view. I typically put these type of button on the toolbar and use spacers to keep them out of the view. Here's some sample code:
Call the segue from the alert view delegate like this:
[self performSegueWithIdentifier: #"done" sender: self];
Also implement this method to do any necessary task to prepare for the segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"done"])
{
// [[segue destinationViewController] setManagedObjectContext:self.managedObjectContext];
// [[segue destinationViewController] setSelectedClient:selectedClient];
}
}
You can create segues directly from the startingViewController to multiple destinationViewControllers that can then be "performed" programmatically. You do not need to create any hidden buttons for them, which does seem like a hack.
OK I came up with a solution in keeping with the storyboard that I like.
Example:
My tableview has 2 sections, grouped, and cells are dynamic prototype. Section 0 contains one row/UITableViewCell & I don't want it to segue. Section 1 contains multiple cells that I want to trigger the segue & drill down into the detail.
In Storyboard:
I removed the segue linking the tableviewcell to the destination view controller.
I made a 'generic' segue linking the source view controller directly to the destination view controller.
In the attributes on the segue, I set the identifier ('EditTimePeriod') and set the type to Push (I presume Modal would work just the same).
In the source view controller:
In the prepareForSegue method I handled both the common 'AddTimePeriod' segue I control-dragged from my UIBarButtonItem (Add), along with the 'generic'(vc-->vc) 'EditTimePeriod' segue.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// handle the click of the 'Add' bar button item
if([segue.identifier isEqualToString:#"AddTimePeriod"]) {
TimePeriodViewController* tpvc = (TimePeriodViewController*)segue.destinationViewController;
tpvc.delegate = self;
// database & entity stuff for adding the new one to the mOC, etc
}
// handle the click of one of the 'editable' cells -
if([segue.identifier isEqualToString:#"EditTimePeriod"]) {
TimePeriodViewController* tpvc = (TimePeriodViewController*)segue.destinationViewController;
tpvc.delegate = self;
TimePeriod * newTP = [self.timePeriodArray objectAtIndex:self.tableView.indexPathForSelectedRow.row];
tpvc.timePeriod = newTP;
}
}
Then I implemented the tableView:didSelectRowAtIndexPath method, and put my condition in here. If the selected row was outside of section zero I called the EditTimePeriod segue manually, defining the sender as the selected tableviewcell:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(self.tableView.indexPathForSelectedRow.section!=0){
[self performSegueWithIdentifier:#"EditTimePeriod" sender:[tableView cellForRowAtIndexPath:indexPath]];
}
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
return;
}
would be nice to code the cell in section 0 so that it is not selectable in the first place!
Hope this helps though.
** and then 5 minutes later I took another look and realized I could just move the data from section 0 into the section header, which is more intuitive and wasn't being used anyway. leaving the design open for a standard segue from each tableviewcell without needing any condition/check. Was a good exercise anyway though :)

Resources