Я заполняю UITableView пользовательскими ячейками UITableViewCell, в каждом из которых есть кнопка. Чтобы проверить, нажата ли кнопка, я использую шаблон протокола делегата. Вот моя реализация:
protocol MyTableViewCellDelegate {
func didPressButtonInTableView(for indexPath: IndexPath)
}
class MyTableViewCell: UITableViewCell {
lazy var indexPath = (self.superview?.superview as! UITableView).indexPath(for: self)
var delegate: MyTableViewCellDelegate!
@IBAction func buttonPressed(_ sender: Any) {
self.delegate.didPressButtonInTableView(for: self.indexPath!)
}
}
Прочитав немного об управлении памятью, я понял, что иногда экземпляры дочернего класса, содержащие ссылки на родительский класс, не освобождаются из-за «цикла сильных ссылок» , поскольку и родительский класс, и дочерний класс имеют сильную ссылку друг на друга. Мы должны использовать ключевое слово weak
, чтобы определить слабую связь, по которой, когда родительский класс освобождается, дочерний класс тоже.
Итак, я понял, что использование делегата содержит сильную ссылку на UITableView (родительский класс). Выполнив некоторые тесты, такие как проверка использования памяти в отладчике Xcode и использование deinit
в дочернем классе, я понял, что эти ячейки представления таблицы не освобождаются. Изменение протокола на использование AnyObject
, а затем установка делегата как weak
устранили проблему. При повторном запуске использование памяти не увеличивалось, и когда я перешел в другое представление, было вызвано deinit
.
При запуске обеих версий кода в Leaks in Instruments утечек памяти в первом случае не было. однако при каждой загрузке табличного представления происходило очень заметное увеличение памяти.
Мой вопрос: почему это не помечено как утечка памяти в инструментах, поскольку дочерний класс имеет сильную ссылка на родительский класс с помощью делегата? В чем разница между этой ссылкой и традиционной ссылкой родительско-дочерней строки, которая вызывает утечки, обнаруженные инструментами?