Swift - @escaping и захватить уточнение списка
Я пытался копаться в этом предмете столько, сколько мог, но все же у меня есть несколько вещей, которые не были решены в моей голове, и я буду благодарен, чтобы получить разъяснения по ним.. поэтому я задал несколько вопросов...
- Как компилятор знает, что я должен добавить @escaping в фоновый поток, и тем самым заставить меня использовать его?
- Есть ли плата за использование @escaping? если нет.. почему бы не отметить всегда? Что может пойти не так, если я отмечу закрытие @escaping, даже если оно мне действительно не нужно? Когда я пытался это сделать... в моем коде не было проблем, и результат с или без @escaping остался прежним.
- Какова стоимость использования списка захвата [слабая личность] [непризнанная личность]? Я знаю, что он создает копию этого объекта, так что я полагаю, что временно это займет больше памяти, но в конце этого использования эта копия будет удалена из памяти... итак, есть еще недостатки в использовании?
1 ответ
Короткие ответы
- Компиляторы используют разные процессы для анализа кода. В колледжах есть множество лекций о том, как работают компиляторы. Поэтому довольно сложно дать вам правильный ответ.
- Используйте то, что вам нужно. Довольно сложно оценить, сколько это стоит. @escaping и @no-escaping имеют разные варианты использования.
- Я не вижу недостатков. Использование слабых - хороший способ предотвратить циклы розничной торговли и утечки памяти.
объяснение
1: Так как именно работает этот компилятор, я действительно не знаю. Но если вы хотите понять, как обычно работают компиляторы, прочитайте несколько легких статей, подобных этой
По моей идее, у компилятора будет лексический анализ, синтаксический анализ и семантический анализ. Таким образом, компилятор определит, нужен ли вам выход или нет.
2: замыкания - это быстрое понятие: "Делай вещи, когда дела идут". Более подробно смотрите в документации и здесь
Следующая информация во многом основана на этой статье " что делать, значит убегать и не убегать-замыкания-в-быстром"
В Swift 1 и 2 замыкания были @escaping по умолчанию. С Swift 3 замыкания @ не выходят.
@ без побега
Когда вы передаете замыкание в аргументах функции, используйте его до того, как тело функции выполнится и вернет компилятор обратно. Когда функция завершается, переданное закрытие выходит из области видимости и больше не существует в памяти.
Проще говоря, это удобная обработка памяти для разработчика, потому что он ни о чем не заботится.
@escaiping закрытия
Для замыканий @escaping есть два варианта использования:
Хранение: когда вам нужно сохранить замыкание в глобальной переменной, выполняется свойство или любое другое хранилище, которое существует в памяти после вызывающей функции, и возвращает компилятор обратно.
Асинхронное выполнение: Когда вы выполняете закрытие асинхронно в очереди отправки, очередь будет держать закрытие в памяти для вас, может быть использовано в будущем. В этом случае вы не знаете, когда будет выполнено замыкание.
Из документации Apple
Говорят, что замыкание экранирует функцию, когда замыкание передается в качестве аргумента функции, но вызывается после ее возврата. [...] вы можете написать @escaping перед типом параметра, чтобы указать, что закрытию разрешено экранировать.
К сведению: закрытие отмечает, что операция является асинхронной и не является обязательной в фоновом потоке.
3: я не вижу недостатков, чтобы использовать это. Использование слабых - хороший способ предотвратить циклы розничной торговли и утечки памяти. Вы должны игнорировать потенциальные затраты, когда вы получаете стабильное приложение. Но я повторяю: используйте то, что вам нужно. С утечками памяти это сложно, и часто их трудно найти.
См. /questions/5064527/kak-sdelat-slabuyu-ssyilku-na-protokol-v-chistom-swift-bez-objc/5064534#5064534 для действительно хорошего ответа о делегатах и утечках памяти. В этом посте также много других ссылок. Если вы прочитаете их, вы получите хорошее / лучшее понимание того, как будут происходить утечки памяти и как их предотвратить.
И проверьте этот пост тоже, он немного похож на ваш /questions/19100189/swift-escaping-i-obrabotchik-zaversheniya/19100205#19100205
Изменить на 3
спрашивающий:
Я предполагаю, что я не понял это правильно... так, что означает "захват", как это действительно работает за сценой с точки зрения непризнанного я? как замыкание использовать себя без владения объектом? может быть, этот вопрос должен быть отдельным от stackru
Вдохновленный примером поста Можно ли получить доступ к памяти локальной переменной вне ее области?
Вы снимаете номер в отеле. Вы выезжаете на следующее утро, запираете дверь, но "забыли" вернуть свой ключ. Ты крадешь ключ! Там нет запасного ключа. Так что номер в отеле заперт. Владелец отеля больше не может арендовать этот номер. Сейчас много гостей, которые крадут ключ. Иногда каждая комната на самом деле свободна, но заперта.
С небольшой фантазией арендатор закрывается. Он снимает комнату (создает ссылки на экземпляр комнаты). Он там спит (асинхронная операция). Он должен вернуть свой ключ, но он этого не делает.
В моем понимании закрытие не владеет объектом. Это ссылка между замыканием и свойством экземпляра.
Документация Apple:
Цикл строгой ссылки также может произойти, если вы назначаете замыкание свойству экземпляра класса, а тело этого замыкания захватывает экземпляр. Этот захват может произойти, потому что тело замыкания обращается к свойству экземпляра, например self.someProperty, или потому что закрытие вызывает метод экземпляра, например self.someMethod(). В любом случае эти обращения заставляют замыкание "захватывать" себя, создавая сильный референтный цикл.
Вы можете решить этот сильный цикл с weak
или же unowned
, В моем opionen изображения, которые Apple использует, чтобы объяснить разницу между weak
а также unowned
действительно хороши: см. Автоматический подсчет ссылок