I am Learning iOS Development with Big Nerd Ranch's latest iOS book. I have chosen to implement their apps in Swift. In one of their apps, they have the following code in Objective C:
- (UIView *)headerView
{
// If you have not loaded the header view yet...
if (!_headerView) {
// Load HeaderView.xib
[[NSBundle mainBundle] loadNibNamed:@"HeaderView" owner:self options:nil]
}
return _headerView;
}
Apple's Swift guide on "@IBOutlet":
When you declare an outlet in Swift, the compiler automatically converts the type to a weak implicitly unwrapped optional and assigns it an initial value of nil. In effect, the compiler replaces @IBOutlet var name: Type with @IBOutlet weak var name: Type! = nil.
As it was pointed out in Lazy loading Properties in swift, there are a couple of different options. None of them in that post explicitly mention lazy initialization with @IBOutlet, so I've done by best to implement their suggestions, and would like to know what would be considered best practices.
Attempt #1(failed): following a similar pattern, as the example from AppDelegate.swift. This brings the issue "'IBOutlet' attribute requires property to be mutable"
@IBOutlet var headerView : UIView {
// If the HeaderView has not been loaded yet...
if !_headerView {
// Load HeaderView.xib
NSBundle.mainBundle().loadNibNamed("HeaderView", owner: self, options: nil)
}
return _headerView!
}
var _headerView : UIView? = nil
Attempt #2(failed): using any variation of "@lazy" with "@IBOutlet" didn't worked because "@lazy" needs an initializer, but if a closure is used, then "@IBOutlet" has the same issue as from Attempt #1
Attempt #3(successful?): this is the only way I was able to get this to work. I got the idea from a somewhat different question, Lazy property initialization in Swift. My understanding of what is happening is headerView is actually declared as "@IBOutlet weak var headerView : UIView! = nil", will only be initialized once with the TableViewController subclass I have, and that initialization will be "lazy" in that it only occurs when the TableViewController needs to be loaded.
@IBOutlet var headerView : UIView
func loadHeaderView() {
// If the HeaderView has not been loaded yet...
if !headerView {
// Load HeaderView.xib
println("loaded HeaderView")
NSBundle.mainBundle().loadNibNamed("HeaderView", owner: self, options: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
loadHeaderView()
tableView.tableHeaderView = headerView
}
So, how can this be improved?
Is viewDidLoad() the correct function to use?
Thanks
A lazily loaded outlet makes no sense- if it's an outlet, it's populated when loading the nib, not from code. If you're loading it from code, it doesn't need to be an outlet, so you can use @lazy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With