Swift - Самостоятельное уточнение списка захвата

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

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
302
3

Ответы 3

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

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

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

«иначе закрытие будет игнорироваться без выдачи ошибки». Закрытие не будет «проигнорировано». Закрытие выполняется, как и в противном случае. Если объект, на который указывает ссылка, замыкание, захваченное как weak, уже деинициализировано при запуске замыкания, ссылка будет иметь значение nil внутри замыкания.

user102008 16.09.2020 08:58

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

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

Другие вопросы по теме