Swift - Lazy loading property that can be redone
I'm looking for a way to lazily load my variable, but I want to be able to do it later and then recreate it on get. For example, in the event that there is a memory preservation warning, I want to clear anything not in use and then recreate it again if necessary.
This is how I would do it in Objective-C and my current interpretation in swift. I'm not sure if it saves a variable to keep the current navigation.
Obj-C execution
@property (strong, nonatomic, readwrite) UINavigationController *navController;
...
- (UINavigationController *)navController {
if (!_navController) {
UIStoryboard *tempStoryboard = [UIStoryboard storyboardWithName:@"SomeStoryboard" bundle:nil];
_navController = [tempStoryboard instantiateInitialViewController];
}
return _navController;
}
...
- (void)didReceiveMemoryWarning
{
if (![self.centerView isEqual:_navController]) {
_navController = nil;
}
}
Fast implementation
var navController :UINavigationController? {
get {
// There is no assignment to the a variable and I can't check if the current value is nil or it recalls the get method and hence re-create it if it is nil.
let tempStoryboard = UIStoryboard(name: "Image", bundle: nil);
let tempNavController: AnyObject = tempStoryboard.instantiateInitialViewController();
return tempNavController as? UINavigationController;
}
}
...
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
if (!self.centerPanel.isEqual(navController)) {
self.navController = nil;
}
}
source to share
The part you're missing is that in Objective-C it creates an _navController
ivar and setter for you ; in Swfit you need to create them yourself.
Once you have tags, your property navController
in Swift can look very similar to Objective-C one:
private var _navController: UINavigationController? = nil
var navController: UINavigationController! {
get {
if _navController == nil {
let tempStoryboard = UIStoryboard(name: "Image", bundle: nil);
_navController = tempStoryboard.instantiateInitialViewController() as? UINavigationController
}
return _navController
}
set {
_navController = newValue
}
}
Note. ... I've stripped navController
as implicitly expanded UINavigationController
so that it can be set to nil
while still making it available without expanding the value every time. While it can be dangerous to use an implicitly expanded type, it does (and does) work in this case. Since we check for nil
in the getter itself, we can guarantee that it will always return no value nil
. Also, even though we are using the conditional downgraded value returned from instantiateInitialViewController
, it can be said that any value returned from this function other than a UINavigationController
would be a programmer error and the resulting crash would be fine.
source to share