Сохранить цикл в закрытии Swift - PullRequest
0 голосов
/ 23 мая 2019

Я вижу много примеров сохранения циклов в Swift.Однако многие из них неверны, и чтение документации не дает по-настоящему простых примеров, которым я могу следовать.

Например:

class Dog {
    func bark() {
        print ("YAP")
    }
}

var dog = Dog()
let doSomething = {
    dog.bark()
}

doSomething()

Является ли замыкание doSomething причиной цикла сохранения?Я понимаю, что закрытие будет выполнено быстро, но это не вопрос.Это по своей сути вызывает сохранение цикла?

Ответы [ 2 ]

2 голосов
/ 23 мая 2019

В сохраненной вами программе нет цикла сохранения.

Что такое цикл сохранения?

Рассматривайте каждый объект (включая каждое замыкание) в вашей программе как одну вершину в ориентированном графе,Рассмотрим сильную ссылку от объекта (или замыкания) A на объект (или замыкание) B как ребро от A до B. График.

Цикл сохранения - это цикл в графе: путь, содержащий как минимумодно ребро (сильная ссылка), ведущее от вершины к себе.

Например, типичный цикл сохранения выглядит следующим образом:

retain cycle from ViewController to View to Closure back to ViewController

Контроллер вида всегда имеет строгую ссылку на свой вид (если вид был загружен).В этом примере контроллер представления создал замыкание.Закрытие захватило (имеет сильную ссылку на) контроллер представления.Затем контроллер представления сохранял замыкание в свойстве представления, создавая цикл сохранения.

Что такое график сохранения вашей программы?

Вот график сохранения вашей программы:

retain graph showing doSomething referencing dog

На этом графике нет циклов сохранения.

0 голосов
/ 23 мая 2019

Вот еще один «пример», который выходит за пределы игровой площадки, чтобы продемонстрировать цикл сохранения с закрытием:

class ClosureClassStrongRefCycle {

    let str : String

    lazy var printStr: () -> () = { // self is captured
        print("\(self.str)")
    }

    init(str: String) {
        self.str = str
    }

    deinit {
        print("ClosureClassStrongRefCycle is being deallocated")
    } 
}

Теперь, когда вы звоните своему классу так:

 do {

      let myClassWithClosureStrongCycle = ClosureClassStrongRefCycle(str: "closure class strong cycle")
      myClassWithClosureStrongCycle.printStr()

 } // 'myClassWithClosureStrongCycle' is NEVER deallocated -> Strong reference cycle between this class and it's closure

экземпляр ClosureClassStrongRefCycle сохраняет себя, потому что закрытие внутри него сохраняет self

наконец, если вы хотите избавиться от цикла сохранения, вы можете добавить unowned self следующим образом:

lazy var printStr: () -> () = { [unowned self] in // Unowned copy of self inside printStr
    print("\(self.str)")
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...