Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am having problem passing value to a IBOutlet property of destinationViewController but it works fine on ordinary property see code below

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"NewsCellToDetail"]) {        
    testViewController *viewController = segue.destinationViewController;
    viewController.titleLabel.text = @"test"; // set the IBOutlet label text to something
    NSLog(@"%@",viewController.titleLabel.text); // this will output to nil
    viewController.textTest = @"testing2"; // set the property to something
    NSLog(@"%@", viewController.textTest) // this will output the string testing2
}

This is the code for the header file testviewcontroller.h

#import <UIKit/UIKit.h>
@interface NewsDetailViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *titleLabel;
@property (strong, nonatomic) NSString *textTest;
@end

I already synthesize both the property.

Thanks for the help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
690 views
Welcome To Ask or Share your Answers For Others

1 Answer

I'm a little late coming into this answer, but I ran into this issue recently, and the reason for this would have been obvious if we were still instantiating things manually instead of letting the storyboard handle it. It so happens to be the same reason you never manipulate the view when manually instantiating view controllers: the segue's destinationViewController has not called loadView: yet, which in a storyboard runs through deserializing all the view objects from the associated nib.

An extremely simple way to see this in action:

  1. Create a two ViewController Scenes (ViewController1 and ViewController2)
  2. Add a button to ViewController1 and an action segue from the button to ViewController2
  3. Add a subview to ViewControler2, and an IBOutlet to that subview
  4. In prepareForSegue: of ViewController1, try to reference that subview outlet of ViewController2 - you'll find it's nil and its frame/bounds are null.

This is because ViewController2's view has not yet been added to view stack, but the controller has been initialized. Thus, you should never try to manipulate ViewController2's view in prepareForSegue: or otherwise anything you do will be lost. Reference Apple's ViewController Programming Guide here for the lifecycle: https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html

The accepted answer here is forcing loadView to run in prepareForSegue: by accessing the .view property of the destination which is why things show up out of order, and will have unknown / difficult to reproduce results if you're trying to do any kind of view manipulation in viewDidLoad to account for any data loads, because without having the view loaded to the viewStack, any references to the parent view for frame references will be nil.

TL;DR; - If you have data that needs to be passed like in the OP's case, set it using public properties on the destination, and then in viewDidLoad of the destination controller, load that data into the view's subviews.

Edit:

Similar question here - IBOutlet is nil inside custom UIView (Using STORYBOARD)

You may also want to utilize viewDidLayoutSubviews: for any subview manipulation.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...