Why UILabel is not initialized?
Asked Answered
H

1

2

The code is from Stanford CS193p. I added a NSLog to check it out. The label seems not being initialized. Any idea?

@interface AskerViewController() <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UILabel *questionLabel;
@property (weak, nonatomic) NSString *question;
@end


@implementation AskerViewController
@synthesize questionLabel = _questionLabel;
@synthesize question = _question;


 - (void)setQuestion:(NSString *)question
{
    _question = question;
    self.questionLabel.text = question;
    NSLog(@"label is %@", self.questionLabel);
}

@end

The NSLog result is:

2012-07-31 01:56:45.177 Kitchen Sink[23931:f803] label is (null)
Headliner answered 30/7, 2012 at 14:55 Comment(6)
Getter and setter of what? They get called when they get called, you need to give more information or this question can't be answered.Klondike
You are right. I revise the post and put on the code to make the question specific.Headliner
Is your UILabel connected/linked to questionLabel?Teenyweeny
setQuestion: does not initialize the label. It only sets the text. IS the label initialized? Is the outlet connected in Interface Builder?Asperity
Positive, questionLabel is connected to the controller via storyboardHeadliner
How to init a UILabel? Could you give me a line of code and tell me where should I insert it?Headliner
K
8

You are probably setting the question string property before you are displaying the view controller, presumably in prepareForSegue:? At this point, the view has not loaded and the label property will still be nil.

You're doing the right thing by having a separate string property, you're just missing the step that you must also set the label's text in viewDidLoad - at this point your label has been instantiated from the storyboard and is ready to use.

If you're setting properties before viewDidLoad is called, the label being nil is expected. And if you're setting properties from prepareForSegue, the view won't have been loaded yet. A view controller won't load it's view and subviews until it needs to display them on screen, and this doesn't happen until the segue is being performed - and as you can guess, prepareForSegue is done before the segue is performed.

Klondike answered 30/7, 2012 at 18:50 Comment(5)
Don't alloc/init a label if there is one in your storyboard. That's where your label will be coming from. If you're setting properties before viewDidLoad is called, the label being nil is expected. And if you're setting properties from prepareForSegue, the view won't have been loaded yet. A view controller won't load it's view and subviews until it needs to display them on screen, and this doesn't happen until the segue is being performed - and as you can guess, prepareForSegue is done before the segue is performed. This has turned into a long comment, I'm going to add it to my answer...Klondike
I see. I put something like segue.destinationViewController.question in prepareForSegue, which calls setQuestion, which in turn try to access questionLabel, which is not loaded yet during segueing as a subview in the view hierarchy of the destination view controller. That's why NSLog returns null.Headliner
Exactly right. You should still keep that code in setQuestion, because you may set the question again while the view is still loaded, you just need that extra bit in viewDidLoad as well.Klondike
Amazing! My thought is just on the same problem: what's the purpose of keeping the code self.questionLabel.text = question; in setQuestion. What if I have no need to set the question again? Because logic flow is to authorize presenting view controller to ask question, which use prepareForSegue to send the question string to presented view controller. The segue sets up the presented controller. The label text gets set in viewDidLoad. I don't want the label is set in any other way. So, in terms of safety, should I just remove the code, hence the custom setter (setQuestion) all together?Headliner
If that's the way you'll always use it, then yes, that would be fine.Klondike

© 2022 - 2024 — McMap. All rights reserved.