Боролся тут с утечками памяти в рабочем проекте. Копание привело к тому, что после ухода из UIViewController далеко не вся память освобождается. Если несколько раз открывать этот UIViewController, возвращаться назад и снова открывать - потребляемая память растёт и не очень слабо освобождается.
Суть проблемы оказалась в протоколах и делегатах. Классическая ошибка. У меня в UIViewController используется UICollectionView с кастомной ячейкой, у которой есть делегат. Мой UIViewController является для каждой ячейки делегатом. Пример реализации протокола и делегата в интернете и книге по Swift выгядит примерно так:
// Protocol
protocol MyCollectionViewCellDelegate {
func someFunc()
}
// UICollectionViewCell
final class MessageCollectionViewCell: UICollectionViewCell {
var delegate: MyCollectionViewCellDelegate?
}
// UIViewController
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// some code....
cell.delegate = self
}
Внутри объекта ячейки у нас strong-ссылка ;на делегата (UIViewController), в результате происходит утечка памяти.
Решение простое - сделать слабую ссылку (weak) для delegate. Для этого придётся указать протоколу, что реализовать его сможет только класс. Структуры уже пролетают, но и нужны в структурах нет. Меняется всё так:
// Protocol
protocol MyCollectionViewCellDelegate: class {
func someFunc()
}
// UICollectionViewCell
final class MessageCollectionViewCell: UICollectionViewCell {
weak var delegate: MyCollectionViewCellDelegate?
}
После этих простых изменений всё стало прекрасно - после возвращения назад из UIViewController использование памяти возвращается на исходный уровень.