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

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.

  • UISegmentedControl text with multiple lines
  • Swift with C struct pointer
  • Upload Photo / File with JSON and custom headers via Swift 3 and Alamofire 4 | iOS | Swift
  • Result of call is unused
  • Authentication with WKWebView in Swift
  • Images not appearing in PFQueryCollectionViewController
  • 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;
        }
    }
    

    Solutions Collect From Internet About “Swift – Lazy loading a property that can be made nil later”

    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.