I had the same issue recently. But when I debug it step by step, I find a possible reason. (Sorry, I'm new to Objective-C too, so my next explanation may not be so accurate and professional ... My previous experience is mostly web development.)
If you set a breakpoint immediately after the line you call
testViewController *viewController = segue.destinationViewController;
when you create and run the project, you will find that the UITextField property in the destinationViewController is not assigned or triggered (memory 0x0) at the breakpoint. Meanwhile, the NSString property is already allocated and initialized (so you can set its value).
I think UITextfield is a child view, so it is only triggered when its parent view (destination view) is triggered. But NSString is a property that is not associated with any view, so it is assigned and initiated using the view controller that declares it.
When I do another test of this, I find it very interesting: the second view is loaded during the runs - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender . I am making test code as below:
In the first view of the controller .m file:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { NSLog(@"1. %@, %@",[segue identifier],segue.destinationViewController); Scene2Controller *scene2ViewController = [segue destinationViewController]; [txtScene2 resignFirstResponder]; NSLog(@"2. scene2ViewController: %@", scene2ViewController); NSLog(@"3. txtScene1: %@; passValue: %@", [scene2ViewController txtScene1], scene2ViewController.passValue); NSLog(@"4. View2: %@; passValue: %@", [scene2ViewController view], scene2ViewController.passValue); NSLog(@"5. txtScene1: %@; passValue: %@", [scene2ViewController txtScene1], scene2ViewController.passValue);
In the second view, the .m file is:
- (void)viewDidLoad { NSLog(@"6. txtScene1: %@; passValue: %@", txtScene1,passValue); [super viewDidLoad]; }
It is noted that I add sequence numbers before NSLog messages. I found that the final sequence of journal results was 1,2,3,6,4,5, not 1,2,3,4,5,6. And in log 3, the result of txtScene1 was null (not initiated), but after log 4 (the second view was loaded), in log 5 txtScene1 was not null and was triggered. This showed that the second view was loaded during the session. Therefore, I assume that during the segue transition, the sequence of initialization of the objects of the second view of the controller will be: the second view controller → the NSString property (and other similar properties, such as NSInteger, etc.) → the second view → the UITextfield property (and other subview properties) .
So, I changed my codes in the .m file of the first file, as shown below:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { Scene2Controller *scene2ViewController = [segue destinationViewController]; [txtScene2 resignFirstResponder]; if ([scene2ViewController view]) { if ([txtScene2.text isEqualToString:@""]) { scene2ViewController.txtScene1.text = @"No Value"; } else { scene2ViewController.txtScene1.text = txtScene2.text; } } }
This code works fine, and the value is passed directly to the UITextfield property in the second view.
The hope of the above explanation is clear and helpful to you.