Swift - самоопределение списка захвата - PullRequest
0 голосов
/ 02 мая 2018

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

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

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

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)
}
0 голосов
/ 02 мая 2018

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

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

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

...