I'm creating an app in Xcode that currently consist of a Navigation Controller a Table View Controller and a regular View Controller.
I'm using StoryBoard and have created a segue between the table view and the regular view controller. In the navigation bar I have a button that I've dragged to the view controller in the StoryBoard. When I click at the button, the new View Controller is viewed like it suppose to. I then tried to pass data from the table view controller, see below:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"läggTill"])
{
// Get reference to the destination view controller
AddPlayerViewController *apv = [segue destinationViewController];
[apv.myTextField setText:#"hello"];
}
}
The segue identifier is "läggTill", but the code inside the if-statement is not executing.
Two questions:
What is wrong with this approach?
Is this the best approach when using StoryBoards? Can I pass data via viewWillDisappear?
Can I use segues to pass data back to the table view controller from the view controller?
It makes all the sense in the world to pass your data in the prepareForSegue:sender:. I would not recommend passing data in viewWillDisappear because it just makes it messy and it reduces readability + it becomes harder to keep track.
I think your string comparison is not working! Put an NSLog for your identifier string see on the console. I have a feeling it might not like the "ä" character in comparison.
About your last question, as Gabriel.Massana pointed out, for passing data back, using delegate is the way to go.
Note 1: Another problem I noticed is a possible typo you might have "apv" and "avc".
Note 2: Another reason for it failing is that you are setting the TextField before viewDidLoad gets called on your destination controller. I suggest that pass it as string and in the viewDidLoad of your destination, set the text to your TextField.
Related
I have two view controllers "SortViewController" and "CatalogeViewController".
I have on "SortViewController" 6 Button which connected with push segue to "CatalogeViewController"
how can i know from which one of the button the user came from?
I set an identifier for the segue and I have thought about prepare for segue and sending an string variable to "CatalogeViewController" while the user press on button and to check if it the same string on "CatalogeViewController".
There is another way to do that?
and please some one can explain me how to do preapre for segue with string variable according to my question.
Thanks
Bouabane's answer would work, but it would require creating a different segue for each button, which is a lot more work initially, harder to maintain, and clutters your storyboard with lots of segue connections.
Since all of your buttons link to the same destination, I would do it differently.
Create a segue manually by control-dragging from your first VC (ViewController) to your second VC. Give it a unique identifier like "ButtonSegue"
Then create an IBAction for all of your buttons. Link all of your buttons to the same action.
Give each button a unique tag number. Use a sequential range of numbers (e.g. 101, 102... 106).
In your IBAction method, save the button's tag number to an instance variable.
In your prepareForSegue, pass the tag number instance variable to your destination VC. (The code to match a number is faster and simpler than the code to match strings. With numbers you can use a switch statement.)
To make the code cleaner and easier to read, I would define a typedef'd enum with the possible tag values, then make your source view controller's tag number instance variable and your destination view controller's tag number property use that type.
You should use this method.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
This is an example how you can accomplish your need:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
CatalogeViewController *catalogeViewController = segue.destinationViewController;;
if([segue.identifier isEqualToString:#"firtsSegue"])
{
catalogeViewController.selectedButton = #"firstButton";
}else if([segue.identifier isEqualToString:#"secondSegue"]){
catalogeViewController.selectedButton = #"secondButton";
}else
.
.
.
}
I'm trying to update a Label in the 2nd VC from the 1st VC within the prepareForSegue method.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
MYSecondViewController* secondVC = (MYSecondViewController*)segue.destinationViewController;
secondVC.titleLabel.text = #"First VC Says: You Are Second!!"; //This doesn't work
secondVC.dataPassString = #"First VC Says: You Are Second!!"; //This works + secondVC viewDidLoad
}
If I update the Label directly, it doesn't work.
If I update a String Property and then assign it to the Label in the Second VC viewDidLoad, it does work.
Does it mean that upon prepareForSegue call the second VC viewDidLoad method was not called yet?
Was some init method called (so the NSString object could pass)? If yes, which one?
Is there a way to update IBOutlets in the 2nd VC from the 1st VC?
The short answer is: Don't do that.
You should treat another view controller's views as private and never try to manipulate them. It breaks the OOD principle of encapsulation.
What you want to do is to add (string or other type) properties to your destination view controller, and set THOSE in prepareForSegue. Then in your destination view controller's viewWillAppear method, copy those property values into the view controllers' views.
In your case, the datePassString property is exactly what you want.
That way, if you change the structure of your second view controller down the road, and decide to display the information to a different view, you don't break the link between the 2 view controllers. Your destination view controller can still fetch the data from it's source, and do something different with it.
P.S. as the other poster said, the reason setting secondVC.titleLabel.text fails is that in prepareForSegue, the destination view controller's views haven't been loaded yet.
If you add in this line in your "prepareForSegue" method:
if(!secondVC.titleLabel)
NSLog(#"titleLabel is null and it likely hasn't been loaded yet")
You'll see that the view hasn't been loaded until it's time for it to appear (which happens after prepareForSegue). That's why the datePassString property you're using is working while the IBOutlets are null until the view is loaded.
I want to pass a photo taken in the first view controller to a second view controller. I want the user to take the photo in the first view controller and then crop in in the second view controller and then save.. So its like.. User take photo→crop→save. I just want to do this simple task but taking me days to get the segue go right.. Is segue the best way to do this? or is there a more easier way to do this task. I am a beginner in objective -c so its making me confused with segues and all the stuff.
You need to implement prepareForSegue:sender: in the source view controller. This will give you access to the destinationViewController via the passed storyboard. Then you can set the image so its available when the destination view controller is displayed.
As far as segue is concerned you need to create a segue arrow using storyboard by dragging arrow from first view controller to second view controller, and most importantly you need to give the segue an identifier or name.
For firing you segue you may do it programatically, like:
[self performSegueWithIdentifier:#"ShowSecondScreen" sender:self];
For handling things when segue is fired you need to write prepareForSegue() method, you may pass any object from current viewController to next viewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ShowSecondScreen"])
{
SecondViewController *secondViewController = segue.destinationViewController;
secondViewController.imageObj = image;
}
}
The kind of design that I'm trying to accomplish in my app currently consists of a navigation controller that is the root controller for another View controller known as Test. Test consists of a UITableView in the top half and an UIImageView in the bottom half. THe navigation bar on the top (which is there as a result of the navigation controller) contains two buttons. The image at the link below ( I don't have the reputation points to post an image directly) should make it very clear.
http://i.imgur.com/GM5eH.png?1
I want my design to be in such a way that depending on which button is pressed the image in the imageview is changed while, though the the text in the table view remains the same, they will transition to completely different screens going forward. To give an example, regardless of which button is tapped my table view will consist of : Option 1, Option 2 and Option 3. However, Option 1 for button A is different from Option B and so on.And, this is where the challenge is for me. I have been able to swap out the images based on the pressing of the button succefully. I did this by using an IBActionNavBarButonPressed and then swapping out the images based on the sender tag. Unfortunately, I don't know how to proceed from here. So for example I have my next couple of screens here. But, how do I set up the segues/transitions in such a way that only Option 1 of choice A goes to a certain screen and so on. From my understanding, I'm looking at a combination of prepareforSegue and the navBarbuttonPress IBAction but I'm still not sure how this would work.
Guys, I'm fairly certain as to what I'm trying to but since I'm new to objective C, I'm not completely sure of how to do it. Essentially, I want the logic to be something like, if(element.selected==0) && (IBActionProvider==1) { performSegueWithIdentifier:#"blah" sender.self]; My issue is whether to put this in the IBAction navBarButtonPressedMethod or to put it in the didSelectRowAtIndexPath method.
Thanks and sorry for the long question!
First you give names to other storyboards views. It contains left hand panel(Storyboard Identifier :).
You should create segue for all buttons and give identifier to it.
Then you should use prepareforSegue like this
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ToContacts"])
{
// Get reference to the destination view controller
ContactVC *targetVC = [segue destinationViewController];
// Pass any objects to the view controller here, like...
targetVC.CompanyNme = selectedRowValue;
}
if ([[segue identifier] isEqualToString:#"ViewCompany"])
{
ContactVC *targetVC = [segue destinationViewController];
targetVC.CompanyNme = selectedRowValue;
}
}
#"ToContacts" means your storyboard identifier.
I have a problem where I am able to pass all data to a push view controller using
[self performSegueWithIdentifier:#"Expense" sender: self];
and
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
However I do not know how to get back data when the view controller is popped out. I have a couple of arrays that need to be passed from a popped view controller to parent view controller.
Create a class to serve as the data model for your application and have it include the arrays you need to pass around. Create an object of that class in your first controller, share it with the second controller during prepareForSegue:, let the second controller update it, and read the new values when the parent's view appears again.
You should use segues to pass data forward and Delegate Methods to send data back in your navigation stack. That is the recommended approach. I answered a similar question earlier. Although the question may sound different, the underlying solution should work in your case as well.