2

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.

lopezdp
  • 1,538
  • 3
  • 21
  • 38
  • Possible duplicate of [Pass back data using \[popviewcontroller\], and reload data](http://stackoverflow.com/questions/24026359/pass-back-data-using-popviewcontroller-and-reload-data) – Janak Thakkar Oct 29 '16 at 06:34
  • You can use KVO(Key value observer , NSNotificationcenter , Protocol) – Janak Thakkar Oct 29 '16 at 06:34
  • how? i do not understand what that means, please this is not a duplicate I have been staring at the duplicate mentioned for three days and it has not been of any help. if you can expand on KVO it would be much appreciated! – lopezdp Oct 29 '16 at 06:36
  • Sure share your Skype id and lets resolve this issue – Janak Thakkar Oct 29 '16 at 06:38
  • oh my god! if you could help me out on this i would be so thankful! its my email: davidplopez@live.com give me a minute to make sure i have turned on – lopezdp Oct 29 '16 at 06:40
  • Possible duplicate of [Passing Data between View Controllers](http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers) – alexburtnik Oct 29 '16 at 06:47
  • thanks @alexburtnik I've spent 3 days looking at every single one of those possible duplicates and yet i am struggling. i was hoping for some help in the right direction... you got any input regarding the question I've posted? – lopezdp Oct 29 '16 at 06:53
  • 1
    You can just use an unwind segue http://stackoverflow.com/questions/12561735/what-are-unwind-segues-for-and-how-do-you-use-them – Paulw11 Oct 29 '16 at 06:57
  • @Paulw11 thanks that link has so far been the most useful bit of info i have come across in regards to explaining the whole process – lopezdp Oct 29 '16 at 07:07
  • @Paulw11 im confused after reading the link you sent, do I have to add another unwind segue in the second view controller? in that additional unwind segue, how do i get the data back into the labelText variable and how do i read the data in the labelText variable from the first view controller so i can display it? – lopezdp Oct 29 '16 at 07:25
  • @Paulw11 based on the link i can tell you that i have an unwind segue already written as you can see in my code and my second scene already goes back to my first scene however, it goes back without the data needed. so i understand the code i have written now in that i know i wrote the unwind segue correctly, i just dont know how to pass the data back using the labelText variable i initially used to pass the data forward. – lopezdp Oct 29 '16 at 07:30

1 Answers1

1

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
}
Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • my problem is that third line you wrote, ive been struggling with that exact part because I cannot access that heightField variable from the FirstSceneViewController.m file. ive tried different iterations of that idea a few times now. I also tried using my labelText variable which is the same (strong, nonatomic) variable I have defined in my SecondSceneViewController.h file to pass the data forward using the destination object in prepareForSegue, but for some reason I cannot Access it in reverse to bring the data needed back.... i am now stumped, I almost thought you had it. – lopezdp Oct 29 '16 at 07:52
  • 1
    I downloaded your project; you need to make a couple of changes. You need to move the `@property (weak, nonatomic) IBOutlet UITextField *heightField;` from the .m file to the .h file and you need to add `#import "SecondSceneViewController.h"` to FirstSceneViewController.m Then the code in my answer will work. – Paulw11 Oct 29 '16 at 09:09
  • OK my Man!! Few questions first: 1. how do i figure out when to put that *heightField in the .h file instead of the .m file? 2. in your code, the *source object is a data of type SecondSceneViewController. this is the delegate coming from the segue of type SecondSceneViewController using the sourceViewControllerMethod. This data is then extraced using the source.heightField.text method. I think I am understanding this correctly? Thank you for the help!! – lopezdp Oct 29 '16 at 09:33
  • 1
    Swift just figures out symbols if they are in your project, but Objective-C, since it is based on C, needs things to be defined explicitly. By putting the property in the .h file and importing that file into the first view controller, the compiler now "knows", while compiling the first view controller that there is such as a class as `SecondSceneViewController` and that it has a property, `heightField` which is a `UITextField` – Paulw11 Oct 29 '16 at 09:35
  • this is awesome. so basically i can use the unwind segue in the exact reverse of the prepareForSegue. is the unwind segue considered a custom segue I assume?? – lopezdp Oct 29 '16 at 09:36
  • `source` isn't a delegate, it is a reference to the instance of the view controller that you are unwinding from, that is all. You need to cast it from `UIViewController` to your specific view controller subclass in order to access its properties. An unwind segue isn't a custom segue. It is part of storyboards. What is cool about unwind segues is they automatically reverse the segue that was used to get *to* the destination in the first place, so if it was a flip, it flips back. If it is a navigation controller push it slides back the other way and so on. – Paulw11 Oct 29 '16 at 09:39