Swift - Lazy loading a property that can be made nil later

落花浮王杯 提交于 2020-01-01 06:43:36

问题


I am looking for a way to lazy load my variable, but I want to be able to make it nil later and then recreate it on the get. For example in the instance that there is a memory warning i want to clear anything that isn't used and then recreate it when needed again later.

Here is how I would do it in Objective-C and my current interpretation in swift. I am not sure that it preserves the variable for keeping current navigation.

Obj-C Implementation

@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;
    }
}

Swift 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;
    }
}

回答1:


The piece that you're missing is that, in Objective-C, it's creating the _navController ivar and setter for you; in Swfit you need to create those yourself.

Once you have those in place, your navController property in Swift can look pretty similar to the 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 delcared navController as an implicitly unwrapped UINavigationController so that it can be set to nil while still making it accessible without unwrapping the value every time. While using an implicitly unwrapped type can be dangerous, it's ok (and appropriate) to use in this case. Since we check for nil in the getter itself, we can guarantee that it will always return a non-nil value. Additionally, even though we're using a conditional downcast on the value returned from instantiateInitialViewController, we can say that any value returned from that function that is not a UINavigationController would be a programmer error and the resulting crash would be appropriate.



来源:https://stackoverflow.com/questions/25953301/swift-lazy-loading-a-property-that-can-be-made-nil-later

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!