Переменные, замыкания и протоколы

Утечка памяти - кошмар для разработчиков, пока вы не поймете, как работает управление памятью в iOS. Если вы ищете детализацию ARC, это не то место. Здесь в первую очередь следует учитывать случаи, когда ARC не может освободить память.

Что такое цикл удержания?

Объяснение одной строкой: если объект, инициализированный в вашем коде, не может быть освобожден сам по себе по каким-либо причинам, тогда начинается цикл хранения.

Представьте, что Боб и Алиса держат друг друга за руки, если Боб хочет покинуть это место, Алиса также должна ослабить его руку. В противном случае Боб остается в памяти даже после того, как он больше не нужен в этом месте. Это обстоятельство называется удерживающим циклом.

Возможное возникновение цикла сохранения

  • Сильная ссылка в классе или структуре
  • Закрытия без слабых или бесхозных
  • Протоколы

Мы рассмотрим каждый из пунктов с примерами блоков кода.

Ссылка на игровую площадку:



Сильная ссылка в классе / структуре

Мы собираемся привезти Илона Маска и его Tesla Model S для нашей демонстрации 😄,

При выполнении вышеуказанной игровой площадки журналы консоли будут такими:

Elon Musk owns TESLA Model S

Не было зарегистрировано деинициализированной печати, причина в том, что объекты Vehicle и Person сильно связаны друг с другом. То же, что Боб и Алиса держат друг друга за руки. Мы должны ослабить узел, добавив weak к объектам, указанным в классах Vehicle и Person.

Разница в приведенном выше коде:

weak var vechicle:Vechicle?

Обновленный журнал консоли

Elon Musk owns TESLA Model S
Vehicle: TESLA Model S is being deinitilized
Person: Elon Musk is being deinitilized

Holahhhh…. мы должным образом освободили место. Боб и Алиса теперь на свободе ...

Закрытие без слабых или бесхозных

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

Этот объект имеет сильную ссылку на замыкание, и, поскольку мы использовали self в блоке замыкания, замыкание имеет сильную ссылку на сам объект.

Мы можем решить эту проблему, добавив к замыканию слабое «я»,

Теперь закрытие больше не имеет решающего значения. Отличие от приведенных выше блоков кода:

vehicle?.batteryFull = { [weak self] in
    self?.unPlugCharger()
}

Другой альтернативный способ - использовать unowned вместо weak, если мы можем гарантировать, что self никогда не будет нулевым.

Просто будьте осторожны при использовании [unowned self], поскольку если объект уже был освобожден при вызове закрытия, произойдет сбой.

Протоколы

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

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

Отличие от исправления выглядит следующим образом:

protocol VehicleDelegate: class {
    func batteryFull()
}
weak var delegate:VehicleDelegate?

После вышеуказанного изменения наш журнал консоли будет следующим:

Elon Musk owns TESLA Model S
Person: Elon Musk is being deinitilized
Vehicle: TESLA Model S is being deinitilized

Здорово! Теперь вы научились избегать циклов сохранения при использовании замыканий, протоколов и var.

Считали этот пост полезным? Пожалуйста, нажмите кнопку 👏 ниже! :)

Оставляйте свои комментарии, вопросы и предложения ниже.