Ответ
Утечка памяти — это ситуация, когда объект более не используется приложением, но не может быть освобожден системой управления памятью (ARC в Swift/Objective-C), потому что на него сохраняется хотя бы одна сильная ссылка (strong reference).
Основная причина в iOS — циклы сильных ссылок (retain cycles):
- Классический пример: Объект
Aсильно ссылается на объектB, аBсильно ссылается наA. - Частый случай с замыканиями: Замыкание, захватывающее
selfбез ослабления ссылки.
class MyViewController: UIViewController {
var onCompletion: (() -> Void)? // Сильная ссылка на замыкание
override func viewDidLoad() {
super.viewDidLoad()
// ОПАСНО: Замыкание создает сильную ссылку на `self`
onCompletion = {
self.view.backgroundColor = .red // `self` захвачен сильно
}
// Теперь: self -> onCompletion -> self (Retain Cycle!)
}
}
// Даже после удаления MyViewController из навигационного стека, память не освободится.
Как избежать утечек:
-
Используйте
weakилиunownedдля разрыва циклов:onCompletion = { [weak self] in // Захватываем weak-ссылку self?.view.backgroundColor = .red // Обращение через optional chaining }weak: Ссылка становитсяnil, когда объект уничтожается. Всегдаoptional.unowned: Предполагает, что объект существует на протяжении всей жизни ссылки. Неoptional. При обращении к разрушенному объекту — краш.
-
Следите за делегатами: Объявляйте свойство делегата как
weak.weak var delegate: MyDelegate? -
Используйте инструменты:
- Instruments > Leaks: Прямое обнаружение утечек.
- Instruments > Allocations: Анализ общего роста памяти и циклических ссылок (кнопка "Mark Generation").
- Визуализация отладки памяти в Xcode: Показывает граф объектов в реальном времени.
Последствия утечек: Постепенный рост потребления памяти (OOM-краши), снижение производительности.