Swift - @escaping и захватить уточнение списка - PullRequest
0 голосов
/ 01 мая 2018

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

  1. Как компилятор узнал, что я должен добавить @escaping в фоновый поток и тем самым заставить меня его использовать?
  2. Сколько стоит использование @escaping? если нет .. почему бы не отметить всегда? Что может пойти не так, если я отмечу закрытие @escaping, даже если оно мне действительно не нужно? Когда я пытался это сделать .. в моем коде не было проблем, и результат с @escaping или без него оставался прежним.
  3. Какова стоимость использования списка захвата [слабая личность] [неизвестная личность]? Я знаю, что он создает копию этого объекта, так что я полагаю, что временно это займет больше памяти, но в конце этого использования эта копия будет удалена из памяти ... так, есть ли еще недостатки в использовании?

1 Ответ

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

Короткие ответы

  1. Компиляторы используют различные процессы для анализа кода. В колледжах есть множество лекций о том, как работают компиляторы. Поэтому довольно сложно дать вам правильный ответ.
  2. Используйте то, что вам нужно. Довольно сложно оценить, сколько это стоит. @escaping и @ no-escaping имеют разные варианты использования.
  3. Я не вижу недостатков. Использование слабых - хороший способ предотвратить циклы розничной торговли и утечки памяти.

Объяснение

1: Так как именно работает этот компилятор, я действительно не знаю. Но если вы хотите получить представление о том, как обычно работают компиляторы, прочитайте несколько легких статей, подобных этой one

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

2: Closures - это стремительная концепция, которая гласит: «Делай вещи, когда дела идут». Для более подробной информации смотрите документацию и здесь

Следующая информация во многом основана на этой статье что-делать-значит-убегать-и-не-спасаться-закрывать-в-быстром

В Swift 1 и 2 закрытия были @escaping по умолчанию. С Swift 3 замыкания @ не выходят.

@ без побега

Когда вы передаете замыкание в аргументах функции, используйте его до того, как тело функции выполнится и вернет компилятор обратно. Когда функция завершается, переданное закрытие выходит из области видимости и больше не существует в памяти.

Проще говоря, это удобная обработка памяти для разработчика, потому что он ни о чем не заботится.

@ escaiping closures

Для @escaping замыканий есть два варианта использования:

Хранение: Когда вам нужно сохранить замыкание в глобальной переменной, выполняется свойство или любое другое хранилище, которое существует в памяти после вызывающей функции, и возвращает компилятор обратно.

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

Из документации Apple

Говорят, что замыкание экранирует функцию, когда замыкание передается как аргумент функции, но вызывается после возврата функции. [...] вы можете написать @escaping перед типом параметра в указывают, что закрытию разрешено сбежать.

К вашему сведению: закрывает отметки о том, что операция является асинхронной и не является обязательной в фоновом потоке.

3: я не вижу недостатков в его использовании. Использование слабых - хороший способ предотвратить циклы розничной торговли и утечки памяти. Вы должны игнорировать потенциальные затраты, когда вы получаете стабильное приложение. Но я повторяю: используйте то, что вам нужно. С утечками памяти это сложно, и часто их трудно найти.

См. https://stackoverflow.com/a/34566876/4420355 для действительно хорошего ответа о делегатах и ​​утечках памяти. В этом посте также много других ссылок. Если вы прочитаете их, вы получите хорошее / лучшее понимание того, как будут происходить утечки памяти и как их предотвратить.

И проверьте этот пост тоже, он немного похож на ваш https://stackoverflow.com/a/46245943/4420355

Изменить на 3

спрашивающий:

Полагаю, я не понял это правильно ... так что значит "захватить", как это действительно работает за сценой с точки зрения непризнанного я? как замыкание использовать себя без владения объектом? может быть, этот вопрос должен быть отдельно от stackoverflow

Вдохновленный примером поста Можно ли получить доступ к памяти локальной переменной за пределами ее области видимости?

Вы снимаете номер в отеле. Вы выезжаете на следующее утро, запираете дверь, но «забыли» вернуть свой ключ. Ты украл ключ! Там нет запасного ключа. Так что номер в отеле заперт. Владелец отеля больше не может арендовать этот номер. Сейчас много гостей, которые крадут ключ. Иногда каждая комната на самом деле свободна, но заперта.

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

В моем понимании замыкание не владеет объектом. Это ссылка между замыканием и свойством экземпляра.

Документация Apple:

Сильный референтный цикл также может произойти, если вы назначите закрытие свойство экземпляра класса, и тело этого замыкания захватывает экземпляр. Этот захват может произойти, потому что тело закрытия обращается к свойству экземпляра, такому как self.someProperty или потому что замыкание вызывает метод в экземпляре, такой как self.someMethod (). В любом случае эти доступы приводят к закрытию «Захватывать» себя, создавая сильный референтный цикл.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...