Быстрые ленивые переменные, которые загружаются более одного раза (вычисляемые свойства?)

Я пытаюсь перевести код 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 (или что-то еще).