lopezdp lopezdp - 1 month ago 5
iOS Question

How do I use an unwind Segue to pass data back from the second view controller to the first view controller?

I have created two view controllers. The first view controller sends a name to the second view controller where the name is used to greet the user and prompt the user for their height in inches.

The problem I am having is in sending the height information back from the second view controller to the first so I can do the conversions that I have to do with the data down the road in order to display it in the first view controller.

In my second view controller (.h file) i have created a property that I am using with the destination method (i think its a method) inside of my prepareForSegue method that I am using to send the nameField information to the second view controller. It looks something like this:

property in SecondSceneViewController.h

#import <UIKit/UIKit.h>

//specifying delegate protocol

@interface SecondSceneViewController : UIViewController
@property (strong, nonatomic) NSString *labelText;

@end


My prepareForSegue method in my FirstSceneViewController.m file looks like this:

#import "FirstSceneViewController.h"

@interface FirstSceneViewController ()
@property (weak, nonatomic) IBOutlet UITextField *nameField;
@property (weak, nonatomic) IBOutlet UIButton *goToScene2Btn;
@property (weak, nonatomic) IBOutlet UITextField *displayField;
@property (weak, nonatomic) NSString *heightInches;

@end

@implementation FirstSceneViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//bring data back from scene2
}


- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SecondSceneViewController *destination = [segue destinationViewController];
destination.labelText = self.nameField.text;
}

-(IBAction)goBackToScene1:(UIStoryboardSegue *)segue
{
//Hello, Adnan, you are 6'3 which is 191cm
self.displayField.hidden = NO;
self.displayField.text = [NSString stringWithFormat:@"Hello, %@, you are %@ inches", self.nameField.text, self.heightInches]; //EXAMPLE OUTPUT
}


@end


this is how my SecondSceneViewController.m file brings the name data forward:

#import "SecondSceneViewController.h"

@interface SecondSceneViewController ()
@property (weak, nonatomic) IBOutlet UILabel *greetingLabel;
@property (weak, nonatomic) IBOutlet UITextField *heightField;


@end

@implementation SecondSceneViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.

//display name collected from scene1 held as strong var labelText
self.greetingLabel.text = [NSString stringWithFormat:@"Hello, %@", self.labelText];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}


/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/



@end


Something I have read suggests using a protocol & delegate to use the unwind method in my FirstSceneViewController to make the first scene a delegate of the second in order to bring the height data back to the first scene.

Should i set up an action in the second scene view controller to take the height data in order set it to labelText so i can use the data through label text in the first scene view controller?

I was thinking about something like this:

self.labelText = self.heightField.text;


Then, i was thinking since labelText now holds the data from the second scene, I could the just use the viewDidLoad method in order to take the labelText data and put it into the variable I have in the first scene view controller with something like this:

self.heightInches = self.labelText;


Unfortunately the strategy above didn't work...

I have tried solutions from every pertinent question on stack overflow but I have come to a dead end and I am not understanding how the process works.

Can anyone help out with a possible strategy to help me figure out this solution?

Here is the link to the project if you want to recreate the problem:

https://www.dropbox.com/s/g69i13uh0e1q5e9/2658.ICW01.zip?dl=0

I am trying to use an unwind segue to pass data back to the first view controller. does anyone have any idea how to properly implement this feature?

My goBackToScene1 is my unwind segue. the main problem I am having is in sending the data back from the second scene to the first scene using this unwind segue. I used the variable labelText to send the data forward from the first scene to the second scene but now I am struggling in figuring out the proper syntax in how to send it back using the same unwind segue.

How do I send the data back from the second view controller to the first view controller using my unwind segue called goBackToScene1?

*UPDATE***UPDATE***UPDATE*

So I've continued my attempts at solving this problem and this is what I have done so far:


  1. I created a secondary connection from the same button that triggers my unwind segue to an action in my SecondSceneViewController.m file.



Here is a picture of the connections made from story board:

Action connection to storyboard

The code for this action sets my labelText variable that is defined as a property in my SecondSceneViewController.h file to the heightInches data entered by the user. Here is my code for my SecondSceneViewController.m file where I try to manipulate the data in labelText using the heightField with the sendHeightToDestinationBtn action:

#import "SecondSceneViewController.h"

@interface SecondSceneViewController ()
@property (weak, nonatomic) IBOutlet UILabel *greetingLabel;
@property (weak, nonatomic) IBOutlet UITextField *heightField;


@end

@implementation SecondSceneViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.

//display name collected from scene1 held as strong var labelText
self.greetingLabel.text = [NSString stringWithFormat:@"Hello, %@", self.labelText];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)sendHeightToDestinationBtn:(UIButton *)sender {
self.labelText = self.heightField.text;
}


here is my code in my SecondSceneViewController.h file showing my labelText @property:

@interface SecondSceneViewController : UIViewController
@property (strong, nonatomic) NSString *labelText;

@end



  1. I then rewrote the code in my prepareForSegue action in my FirstSceneViewController in order to use it accordingly in my unwind segue I have called: goBackToScene1. Here is my code for my FirstSceneViewController.m file:

    import "FirstSceneViewController.h"



    @interface FirstSceneViewController ()
    @property (weak, nonatomic) IBOutlet UITextField *nameField;
    @property (weak, nonatomic) IBOutlet UIButton *goToScene2Btn;
    @property (weak, nonatomic) IBOutlet UITextField *displayField;
    @property (weak, nonatomic) NSString *heightInches;

    @end

    @implementation FirstSceneViewController


    • (void)viewDidLoad {
      [super viewDidLoad];
      // Do any additional setup after loading the view, typically from a nib.
      //bring data back from scene2
      }

    • (void)didReceiveMemoryWarning {
      [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
      }



    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    if([segue.sourceViewController isKindOfClass:[FirstSceneViewController class]])
    {
    SecondSceneViewController *destination = [segue destinationViewController];
    destination.labelText = self.nameField.text;
    }
    else if ([segue.sourceViewController isKindOfClass:[SecondSceneViewController class]])
    {
    SecondSceneViewController *source = [segue destinationViewController];
    self.heightInches = source.labelText;
    }

    }

    -(IBAction)goBackToScene1:(UIStoryboardSegue *)segue
    {
    //Hello, Adnan, you are 6'3 which is 191cm
    self.displayField.hidden = NO;

    self.displayField.text = [NSString stringWithFormat:@"Hello, %@, you are %@ inches", self.nameField.text, self.heightInches]; //EXAMPLE OUTPUT


    }

    @end



As you can see i am trying to use the prepareForSegue to determine when to use the labelText variable that I am trying to use in order to pass the data I need back and forth but I can only get it to work from the first view controller to the second and not in reverse.


  1. Here is the output after the unwind segue does what it does.



Program Output

As you can see from the output the data I am trying to pass from the second scene, which is the heightInches variable I am trying to pass through labelText from the heightField in the SecondSceneViewController outputs to (null)...

How do I get the correct data in this variable??? I know i am not using the unwind segue correctly based on the output...

How do I find a strategy to solve this problem correctly???

Please help!

Thanks.

Answer

You almost have it. You have the unwind segue method, you just aren't using it. You can access the second view controller via the sourceViewController property of the segue that is passed to your unwind method:

-(IBAction)goBackToScene1:(UIStoryboardSegue *)segue
{
    //Hello, Adnan, you are 6'3 which is 191cm
    self.displayField.hidden = NO;
    SecondSceneViewController *source = (SecondSceneViewController *)segue.sourceViewController;
    self.heightInches = source.heightField.text
    self.displayField.text = [NSString stringWithFormat:@"Hello, %@, you are %@ inches", self.nameField.text, self.heightInches]; //EXAMPLE OUTPUT
}
Comments