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

      

+3


source to share


1 answer


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.

+4


source







All Articles