Swift Lazy Variables that Load more than Once (Computed Properties?)

ios, lazy-loading, objective-c, swift

Solution

You can create something similar to the Objective-C method using a computed property backed by an optional variable.

var _fetchedResultsController: NSFetchedResultsController?

var fetchedResultsController: NSFetchedResultsController {
    get {
        if _fetchedResultsController != nil {
            return _fetchedResultsController!
        }
        //create the fetched results controller...
        return _fetchedResultsController!
    }
}

Problem

I'm trying to translate some Objective-C code that was essentially lazy loading a variable multiple times. The code was similar to the following: ``` -(NSFetchedResultsController *)fetchedResultsController { if (_fetchedResultsController != nil) { return _fetchedResultsController; } //...code to build the fetchedResultsController with a new predicate ``` Whenever they wanted to rebuild the fetchedResultsController to use a new predicate, they would just set it to "nil" and call it, and it would rebuild it with a new predicate. I'm struggling to do this same task in Swift. As far as I can tell, Swift lazy variables become normal variables after they are called for the first time. This is causing issues for me because if I try to set my swift variable back to nil, and recall it, it doesn't rebuild but remains nil. The working code to load my fetchedResultsController as a lazy varaible is below. I've tried changing it to a computed property by adding a check if its nil and have it within a get block, but that hasn't worked. Any ideas? ``` lazy var taskController : NSFetchedResultsController? = { var subtaskRequest = NSFetchRequest(entityName: "Subtasks") var segIndex = self.segmentedControl.selectedSegmentIndex subtaskRequest.predicate = NSPredicate(format: "task.category.name == %@", self.segmentedControl.titleForSegmentAtIndex(segIndex)!) subtaskRequest.sortDescriptors = [NSSortDescriptor(key: "task.englishTitle", ascending: true), NSSortDescriptor(key: "sortOrder", ascending: true)] let controller = NSFetchedResultsController(fetchRequest: subtaskRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: "task.englishTitle", cacheName: nil) controller.delegate = self return controller }() ```

Original source