iPhone - Cannot access to an IBOutlet (nil valued)
-
11-10-2019 - |
Question
I have a problem accessing a IBOutlet.
I have a NIB inside which there is a tableview, a toolbar and an UILabel (encapsulated into a view). The controller (that is the file's owner) is defined as:
@interface ChoixPeriodeController : UIViewController <UITableViewDelegate> {
IBOutlet UILabel* __periodeInitialeLabel;
}
@property(nonatomic, retain) UILabel* periodeInitialeLabel;
- (void) setSelectedPeriode:(Tache_TypePeriode)typePeriode;
with @synthetize periodeInitialeLabel = __periodeInitialeLabel;
In the .m file, this function is called by the parent window to init the Label :
- (void) setSelectedPeriode:(Tache_TypePeriode)typePeriode {
NSMutableString* tmpString = [NSMutableString string];
[tmpString appendFormat:some text format....];
self.periodeInitialeLabel.text = tmpString;
}
Into this function, I can see that self.periodeInitialeLabel is at nil. I can't see why. Everything is connected into IB... Do you see what can be the problem?
Solution
The question here is the order of operations. If the text label is still nil, it's likely it hasn't been set up yet. Instead, you can call this method inside of the UIViewController method viewDidLoad
to handle operations like this that must do "extra configuration" that couldn't be done in Interface Builder.
There is also awakeFromNib
. They are very similar, except that awakeFromNib is called ONCE when the NIB file is unpackaged. viewDidLoad
can be called many times - for example, if there is a low memory situation (often happens on iOS4), your views will be purged via viewDidUnload
.
OTHER TIPS
For anyone still having trouble with this, I was facing something similar even in a sample app. The answer turned out to be this:
UIImageView Created In Interface Builder Set To nil When Needed
[self memberVar]
Loads the property, while:
self.memberVar
Just accesses the current value, which will remain nil. So I'm trying to get away from using the "." operator. This is a very subtle issue that I've seen in a lot of sample code lately. The underscore method in the newer examples:
@synthesize memberVar = _memberVar;
still just leaves the member variable nil until you access it with [self memberVar]
. I think Apple may be trying to avoid the issue by referring to _memberVar in the implementation ( for example in dealloc
with [_imageView release]
)
UPDATE: Also, if you are using initWithNibName
or loadNibNamed
to load a controller from a nib or xib on the fly (for example a custom UITableViewCell
), don't forget to call:
[self loadView];
This also loads the member variables. They aren't loaded automatically unless the view is shown or does pushViewController
onto a navigationController
.
I think your property has to be defined with IBOutlet as well, like:
@property(nonatomic, retain) IBOutlet UILabel* periodeInitialeLabel;
and you need to @synthesize
the property in your implementation file, and then make sure periodeInitialeLabel
is wired up correctly in IB (i.e. not `__periodeInitialeLabel');
Update:
If your synthesize statement looks like this:
@synthesize periodeInitialeLabel;
then that's probably your problem. I think it has to be this:
@synthesize periodeInitialeLabel = __periodeInitialeLabel;
to hook it up to your field.
Given this interface:
@interface ChoixPeriodeController : UIViewController <UITableViewDelegate> {
UILabel* __periodeInitialeLabel;
}
// I think it's more appropriate to mark a property with IBOutlet,
// rather than an ivar
@property(nonatomic, retain) IBOutlet UILabel* periodeInitialeLabel;
- (void) setSelectedPeriode:(Tache_TypePeriode)typePeriode;
// ...
@end
its implementation should look like this:
@implementation ChoixPeriodeController
@synthesize
periodeInitialeLabel = __periodeInitialeLabel;
// the rest of your implementation goes here
// ...
@end
I would also suggest you to look at the Google Objective-C Style Guide. Naming your ivars with two leading underscores may not be the best choice.