For reference, I’m trying to learn Objective-C through the Stanford iTunes-U course. I wanted to update one property from the setter of another (they are inherently connected. Also, is that bad style?). The property I am trying to update is a UILabel, but it doesn’t work like I thought.
This code is in one of my view controllers:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[segue.destinationViewController setProgram:self.brain.program];
}
Naturally, this code calls the setter for the Program property of the incoming viewController. Here’s that setter code:
-(void)setProgram:(id)program {
_program = program;
self.title = [CalculatorBrain descriptionOfProgram:program];
[self.graphview setNeedsDisplay];
self.testLabel.text = @"Trying to update your text!";
}
and the header file:
#import <UIKit/UIKit.h>
@interface GraphViewController : UIViewController
@property (nonatomic, strong) id program;
@property (weak, nonatomic) IBOutlet UILabel *testLabel;
@end
Now, when this code is run, as the segue happens, the new view DOES have its title changed (the self.title line works). However, the UILabel DOES NOT get updated. Furthermore, if I call the setter again say in viewDidLoad, it does change the UILabel. Is this because of self being updated? What’s going on here?
In one of the lectures, the professor explains that outlets aren’t set yet in prepareForSegue. This means testLabel is nil, and you’re sending a message to nil (which is allowed and doesn’t crash your app). To solve your problem, set the textLabel’s text in viewDidLoad or viewWillAppear.
I believe this is “fixed” in iOS 6, but it won’t be backwards compatible, so if you want to support iOS 5 still, you’ll have to use viewDidLoad or viewWillAppear to update outlets (which I think is better to do anyway).