Swift - самоопределение списка захвата

После прочтения некоторых статей и руководства для разработчиков по Apple, я все еще не уверен насчет Capture List в завершении. Что означает "захват", как это работает за сценой с точки зрения непризнанного себя и слабого себя? как замыкание использовать себя без владения объектом? Я думал, что это как создание копии этого объекта, поэтому, когда он закончится, он передается из стека, как тип значения, но я думаю, что я не прав. Я надеюсь, что кто-то здесь может сделать это более простым и понятным для понимания, или связал меня с хорошей статьей, которая отвечает на этот конкретный вопрос. Спасибо за продвижение

2 ответа

Мое понимание, и это может быть немного упрощено, заключается в том, что речь идет о владении и удержании объекта, то есть, пока мы заявляем о владении объектом, он не может быть освобожден из памяти, даже если другая часть кода устанавливает его к нулю или тому подобное.

С weakмы говорим, что уничтожать объект можно, и мы будем использовать его, только если он еще есть.

Так, когда декларирует self как weak в заключение мы говорим, что если self все еще существует, когда пришло время выполнить замыкание, которое мы делаем обычно, иначе закрытие будет игнорироваться без возникновения ошибки.

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

class MyClass {
    var myClosure: (() -> Void)!

    init() {
        myClosure = {
            self.foo()
        }
    }

    func foo() {
    }
}

В приведенном выше примере MyClass сохраняет ссылку на myClosure и наоборот, это означает, что MyClass экземпляр останется в памяти навсегда.

У вас также могут быть более сложные / трудные для удержания циклы хранения, поэтому вам нужно действительно обратить внимание, и если у вас возникнут какие-либо сомнения, добавьте несколько print звонки в ваш класс deinit методы просто чтобы убедиться (или использовать инструменты).

Чтобы избежать этих проблем, вы можете пометить объекты, захваченные в замыканиях, как unowned или же weak, Это означает, что их счетчик ссылок не будет увеличен, и вы можете избежать этих циклов сохранения. Приведенный выше пример можно было бы сделать так:

myClosure = { [weak self] in
    self?.foo()
}

или, еще лучше для этого примера, таким образом:

myClosure = { [unowned self] in
    self.foo()
}

Хотя первый путь всегда безопасен и то, что вы будете делать с большей вероятностью, unowned версия легко рассуждать в этом примере, потому что вы знаете, что myClosure не переживет self, Однако, если вы не уверены на 100%, что self всегда переживет закрытие использования weak,

Также обратите внимание, что вы можете отметить, как захватить несколько объектов, используемых внутри замыкания, просто разделив его запятыми, например

myClosure = { [weak self, unowned bar] in
    self?.foo(bar)
}

Если мы будем помнить, что захваченные значения по умолчанию являются сильными ссылками в замыканиях, мы можем предположить, что это может создать циклы сохранения (плохие вещи).

Список захвата - это массив переменных, которые вы можете передать в замыкание. Списки захвата предназначены для изменения силы передаваемых переменных. Это используется для прерывания циклов сохранения.

Например:

// strong reference
[label = self.myLabel!] in

// weak reference
[weak label = self.myLabel!] in

// unowned reference
[unowned self] in
Другие вопросы по тегам