August 9, 2012
I seem to run accross a lot of developers lazily loading their properties. As an example:
- (UILabel *)myTextLabel {
if (_myTextLabel == nil) {
_myTextLabel = [[UILabel alloc] init
[self addSubview:_myTextLabel
}
}
At least in iOS developement, I suspect this is caused by Apple’s sample code, particularly Apple’s default setup for Core Data projects. There are some valid reasons why you’d want to lazily load a resources, but there’s lots of great reasons why you shouldn’t. Here’s a few:
Property calls should not have side effects
There are lots of exceptions for setters (like updating the UI after setting a property), but there are very few exceptions for getters. You shouldn’t need to worry about your object changing state when you access a property.
Lazy loading is confusing
self.myTextLabel = nil
if (self.myTextLabel) {
NSLog(@"What the shit? How did I get here?"
}
Lazy loading leads to tricky initialization order dependences
- (UILabel *)myTextLabel {
if (_myTextLabel == nil) {
_myTextLabel = [[UILabel alloc] init
_myTextLabel.text = self.myTitle
[_myTextLabel sizeToFit
[self addSubview:_myTextLabel
}
}
Now your label will have different text depending on whether you set myTitle
before or after you access myTextLabel
.
Lazy loading leads weird code
Like this:
if(self.myTextLabel) // just need to setup my text label
Initialization, layout, UI updates should be localized
You should be performing all initialization in the init method, UI updates in an update UI method and layout in layoutSubviews
. Not only does this make debugging far easier (having layout issues? I feel bad for you, son. I’ve got 99 problems, but performing view layout anywhere other than layoutSubviews
isn’t one.), but it ensures that your view is always in a consistent state. Big Nerd Ranch has a great writeup on why this is important.
Clearly there are exceptions to all these rules and situations where lazily loading your view properties is the right thing to do. But remember, always write code that emphasizes clarity first and optimize for speed or memory constraints later.
« OK. For serious this time | Home | Configure git to only push current branch »