0

In my app users are required to verify their phone number to register. In the first view, they enter their phone number and receive an SMS. In the second view, they enter the SMS code, and in the third view, they complete their profile.

I am trying to pass the value of the user's phone number from View 1 to View 3.

Please see below:

View1.m

    ProfileCreateViewController *pc = [[ProfileCreateViewController alloc] init];

    pc.userPhoneNumber = [NSString stringWithFormat:@"%@", self.userPhoneNumber.text];

    // Perform segue to View 2

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    EnterCodeViewController* vc = [segue destinationViewController];
    vc.verification = _verification;

}

View 3.h

@interface ProfileCreateViewController : UIViewController

.....

@property (nonatomic, strong) NSString *userPhoneNumber;

@end

View3.m

@synthesize userPhoneNumber;

- (void)viewDidLoad {

    [super viewDidLoad];
    NSLog(@"My phone number is: +1%@", userPhoneNumber);

}

However, when I get to View3, in the log I am getting 'My phone number is +1(null)'

Why isn't the value passing to View3?

Wyetro
  • 8,439
  • 9
  • 46
  • 64
Adam G
  • 1,188
  • 10
  • 24
  • Two things : are you sure that the passed value is non-null? Second - why do you use `@synthesize`? – Losiowaty Aug 23 '15 at 23:23
  • it's definitely non-null ... and I guess it's just a force of habit. – Adam G Aug 23 '15 at 23:26
  • 2
    You wrote in code comment `perform segue` - can you post a whole implementation of `prepareForSegue:sender:`? Or specifically, how do you present `ProfileCreateViewController`? – Losiowaty Aug 23 '15 at 23:31
  • 1
    It's definitely suspicious that you're talking about a segue when you already have created a controller and given it the number. If you're really invoking a segue using a storyboard, that's going to create **another** controller that's not the one you created in the posted code. – Phillip Mills Aug 24 '15 at 01:18
  • Use NSUserdefaults ..... – Sam B Aug 24 '15 at 02:25
  • If you search for '[objective-c] pass data,' what do you find? What makes your case so special? – El Tomato Aug 24 '15 at 03:42
  • 1
    IMHO you deal with two instances. You could use NSUserDefault or a Singleton to cache and retrieve your data instead of instantiating ProfileCretaViewController in View1.m. – Jan ATAC Aug 24 '15 at 05:27
  • I've added my prepareForSegue method in the edit above. Please note that I am performing a segue to View 2, however I am trying to pass the value to View 3. – Adam G Aug 24 '15 at 17:14
  • How do you get to View 3? Do you segue or present it modally? – Wyetro Aug 24 '15 at 17:28
  • I segue to it from View 2 – Adam G Aug 24 '15 at 17:37
  • Post your code with that prepareForSegue – Wyetro Aug 24 '15 at 18:10

4 Answers4

2

If you are using segues you just need to implement the method prepareForSegue like this:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue.destinationViewController class]
      isSubclassOfClass:[ProfileCreateViewController class]]) {
        ProfileCreateViewController *profileCreateVC =
    (ProfileCreateViewController *)segue.destinationViewController;
        profileCreateVC.userPhoneNumber = [NSString stringWithFormat:@"%@", self.userPhoneNumber.text];
    }
}
Fran Martin
  • 2,369
  • 22
  • 19
  • I've added my prepareForSegue method in the edit above. Please note that I am performing a segue to View 2, however I am trying to pass the value to View 3 – Adam G Aug 24 '15 at 17:15
  • If you want to pass a value from your controller 1 to your controller 3, you need to save your value from your controller 1 in a global property, an instance singleton, database or NSUserDefaults. This depends of your app's design. Do you have a reference to your controller 1 in your project? – Fran Martin Aug 24 '15 at 21:28
1

I would suggest with my little Objective C experience that you could save the object to NSUserDefaults or you could just save the string and then retrieve at the 3rd view.

To save only the string:

NSUserDefaults *saveNumber = [NSUserDefaults standardUserDefaults];
    [saveNumber setObject:self.userPhoneNumber.text forKey:@"usersPhoneNumber"];
    [saveNumber synchronize];

Then load it back to the View3.m

NSString *phoneNum = [[NSUserDefaults standardDefaults]objectForKey:@"usersPhoneNumber"];
NSLog(@"My phone number is:+1%@",phoneNum);

I am not sure if this is what you are looking for, but I hope it helps

(In order to save the whole object you will have to use -encodeWithCoder & -initWithCoder at the View3.m file and the perform [NSKeyedArchiver archiveWithRootObject:yourObject] to NSData and then save the NSData to the NSUserDefaults).

  • This is what I would do too – Wyetro Aug 24 '15 at 17:27
  • I guess I should stop trying to make things more difficult than I need. This will work..however, for my own future reference, I'd still like to know why my code isn't working. – Adam G Aug 24 '15 at 17:36
  • Well there is a useful reference I had also used in the past: http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers Hope it helps :) – George Papagiannis Aug 25 '15 at 20:45
0

Use copy instead of strong

@property (nonatomic, copy) NSString *userPhoneNumber;

Check if you have set nil to the textField's text elsewhere. Use NSLog before assigning the text to verify that the text is being assigned or hard code a string to verify you are really getting nil in VC3.

Rohit Kumar
  • 877
  • 6
  • 20
0

"for my own future reference, I'd still like to know why my code isn't working"

Hi there, It is difficult for me to know without a complete code sample. However, from what you have posted I think my guess here is correct.

In View1 when you manually alloc/init the "ProfileCreateViewController" you are creating an instance of the viewController and setting a property on it. However, if you are then using a storyboard segue from viewController2 (EnterCodeViewController) to show viewController3 (ProfileCreateViewController) the storyboard segue will instantiate a ProfileCreateViewController for you, and the one you have created will just be ignored.

I believe what want to do is build some sort of service (I guess you could store it in NSUserDefaults as the other guy suggested). The other thing you can do is create a "UserProfile" object inside the ProfileCreateViewController. This will have a property "phoneNo" and "verificationCode". As you get the data, you populate the object and then pass the object to "EnterCodeViewController" which will then check the verification against the expected code, then if it succeeds pass the full object to the final viewController (ProfileCreateViewController) inside "PrepareForSegue".

If you are using storyboard segue's to manage all of your Segue's you should almost never have to manually alloc/init a viewController.

You can confirm this by pausing in the debugger and taking a note of the memory address of the one you alloc/init and then pause again and take the memory address of "self" once you are inside the "ProfileCreateViewController" with the null property. The memory address's will be different.

If you are still having trouble if you post more of the source code I can help you out. You seem to be new to iOS development. I recommend you check out "http://www.raywenderlich.com". This is a site that has been used by lots of people to learn the basics of iOS and is pretty good! Hope this helps.

Rufus Mall
  • 569
  • 4
  • 14