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
}()
Swift's lazy properties let us delay the creation of a property until it's actually used, which makes them like a computed property. However, unlike a computed property they store the result that gets calculated, so that subsequent accesses to the property don't redo the work.
But what is the difference between a lazy variable and a computed property? A lazy variable is a stored property whose initialization is delayed. The initial value is computed only one time. A computed property is a value that is not stored anywhere.
A lazy var is a property whose initial value is not calculated until the first time it's called. It's part of a family of properties in which we have constant properties, computed properties, and mutable properties.
lazy initialisation is a delegation of object creation when the first time that object will be called. The reference will be created but the object will not be created. The object will only be created when the first time that object will be accessed and every next time the same reference will be used.
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!
}
}
lazy
just implements a very specific memoization pattern. It's not as magical as you'd sometimes like it to be. You can implement your own pattern to match your ObjC code pretty easily.
Just make a second private optional property that holds the real value. Make a standard (non-lazy) computed property that checks the private property for nil and updates it if it's nil.
This is pretty much identical to the ObjC system. In ObjC you had two "things," one called _fetchedResultsController
and the other called self.fetchedResultsController
. In Swift you'll have two things, one called self.fetchedResultsController
and the other called self._cachedFetchedResultsController
(or whatever).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With