Быстрые ленивые переменные, которые загружаются более одного раза (вычисляемые свойства?)
Я пытаюсь перевести код Objective-C, который по существу ленился, загружая переменную несколько раз. Код был похож на следующий:
-(NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
//...code to build the fetchedResultsController with a new predicate
Всякий раз, когда они хотели перестроить fetchedResultsController для использования нового предиката, они просто установили бы его "nil" и назовут его, и он восстановит его с помощью нового предиката.
Я пытаюсь выполнить эту же задачу в Swift. Насколько я могу судить, Swift ленивые переменные становятся нормальными переменными после их вызова в первый раз. Это вызывает проблемы для меня, потому что, если я попытаюсь вернуть свою быструю переменную в нуль и вспомнить ее, она не будет восстанавливаться, но останется нулевой.
Ниже приведен рабочий код для загрузки моего fetchedResultsController в качестве ленивой версии. Я попытался изменить его на вычисленное свойство, добавив чек, если его нуль и его в блоке get, но это не сработало. Любые идеи?
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
}()
Ответы
Ответ 1
Вы можете создать нечто похожее на метод Objective-C, используя вычисляемое свойство, поддерживаемое необязательной переменной.
var _fetchedResultsController: NSFetchedResultsController?
var fetchedResultsController: NSFetchedResultsController {
get {
if _fetchedResultsController != nil {
return _fetchedResultsController!
}
//create the fetched results controller...
return _fetchedResultsController!
}
}
Ответ 2
lazy
просто реализует очень специфический шаблон memoization. Это не так волшебно, как вам иногда хотелось. Вы можете реализовать свой собственный шаблон в соответствии с вашим кодом ObjC довольно легко.
Просто сделайте второе частное необязательное свойство, которое содержит реальное значение. Сделайте стандартное (нелазное) вычисляемое свойство, которое проверяет частное свойство для nil и обновляет его, если оно равно нулю.
Это в значительной степени идентично системе ObjC. В ObjC у вас было две "вещи", одна из которых называлась _fetchedResultsController
, а другая - self.fetchedResultsController
. В Swift у вас будет две вещи, одна называется self.fetchedResultsController
, а другая - self._cachedFetchedResultsController
(или что-то еще).