Печать сильных владельцев объекта, Swift

В моем приложении iOS есть цикл сохранения.

Для конкретного viewController, застрявшего в цикле сохранения, я попытался сделать все делегаты слабыми. Но когда я имитирую предупреждение памяти из симулятора, вызывается didRecieveMemoryWarning, но метод deinit не вызывается.

Я хочу распечатать/увидеть владельца этого viewController, который все еще удерживает его, когда вызывается didRecieveMemoryWarning. Есть ли способ сделать это.


person ila    schedule 21.12.2015    source источник
comment
Я могу ошибаться, но я не думаю, что вы можете. – Пробовали ли вы профилировать с помощью инструмента Leaks? Это может показать сохранение циклов.   -  person Martin R    schedule 21.12.2015
comment
Я не знаю прямого пути, но если вы запустите приложение с подключенными инструментами и используете шаблон Allocations, вы можете посмотреть отдельные объекты и увидеть их историю.   -  person Phillip Mills    schedule 21.12.2015
comment
Обратите внимание, что получение предупреждения о памяти не означает, что что-либо автоматически освобождается: вы должны освободить любые объекты, на которые у вас есть сильные ссылки и которые либо больше не нужны, либо могут быть созданы заново, когда они потребуются. Сам контроллер представления будет освобожден только после того, как он будет удален из иерархии контроллеров представления.   -  person jcaron    schedule 21.12.2015
comment
Вы использовали ntimer в своем контроллере? если ДА, убедитесь, что этот таймер недействителен, когда контроллер не используется   -  person larva    schedule 21.12.2015


Ответы (3)


Нет, нет способа напечатать владельцев объекта, как вы описываете, по крайней мере, не совсем так. iOS не использует сборку мусора, она использует ARC (автоматический подсчет ссылок). Система не отслеживает владение ссылками в ARC. Вместо этого каждый раз, когда вы добавляете ссылку на объект, система увеличивает счетчик сохранения, и каждый раз, когда вы очищаете ссылку на владельца, система уменьшает счетчик сохранения.

Что вы можете сделать, так это запустить вашу программу с помощью инструмента памяти. (Существует приложение отладки под названием «Инструменты», вы выбираете шаблон отладки, называемый «инструмент», который вы используете в программе «Инструменты».) С помощью инструмента памяти вы можете отслеживать жизненный цикл объекта, а также отслеживать количество активных объектов в куче вашего приложения. Когда вы выбираете объект в списке текущих активных объектов, вы можете увидеть, где в вашей программе он был выделен и откуда берется код, который создает сильные ссылки. Однако объяснение того, как использовать инструменты, выходит за рамки поста SO. На эту тему есть различные учебные пособия и видеоролики с сессий WWDC. Предлагаю заняться поиском.

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

Кроме того, вы должны сделать ссылки на делегаты слабыми по умолчанию. Наличие сильной ссылки на делегата ОЧЕНЬ необычно. Я видел его только один или два раза, по определенным причинам.

person Duncan C    schedule 21.12.2015

Если вы используете Xcode 8, вы можете использовать отладчик графика памяти, чтобы визуально увидеть график активной памяти для объектов в ваших проектах. Вы можете перейти к отладчику графика памяти, используя значок с тремя кружками, показанный ниже. введите описание изображения здесь

Отладчик графа памяти был освещен на WWDC 2016 в следующей лекции, которая началась примерно в 24:30.

https://developer.apple.com/videos/play/wwdc2016/410/

person weber    schedule 04.10.2016
comment
Чистое золото! Большое спасибо бро ;) - person Paulo Mattos; 02.08.2017
comment
Хорошая мысль об отладчике графа памяти. Это очень удобный инструмент для определения циклов сохранения и других проблем с памятью. (проголосовали) - person Duncan C; 12.04.2019

Вы можете сделать печать методом deinit, например

class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}

Вы можете проверить это: Автоматический подсчет ссылок

person marchiore    schedule 21.12.2015