Как определить сильные ссылочные циклы в Swift?

Есть ли инструмент или метод для поиска сильных циклов ссылок в моем SWIFT-коде?

Сильный ссылочный цикл - это когда два экземпляра классов ссылаются друг на друга без надлежащих мер безопасности (weak/unowned), поэтому не позволяют сборщику мусора избавиться от них, как только все созданные мной переменные перестанут ссылаться на эти объекты.

Ответ 1

Вы можете добавлять функции deinit в свои классы, которые будут вызываться, когда ваши объекты будут освобождены.

Если deinit не вызывается, пока приложение работает, вы можете нажать кнопку Graph Debug Memory Graph (обведенный ниже) и проверить, что имеет отношение к чему.

Кнопка графика отладки памяти

Используйте раскрывающиеся меню в верхней части средней панели для переключения между классами и экземплярами классов.

Если что-то получает выделение снова и снова без освобождения, вы должны увидеть несколько экземпляров, и вы сможете увидеть через наклонный график, если один из его дочерних элементов имеет сильную ссылку на его родителя.

Ответ 2

Метод поиска сильных эталонных циклов в Swift аналогичен методу Objective-C.

Вы запускаете приложение из Xcode, выполняете приложение достаточно, чтобы манифестировать цикл, а затем нажмите на кнопку "график отладочной памяти" (< img src= "https://i.stack.imgur.com/QC48M.png" alt= "график отладки памяти" > ). Затем вы можете выбрать неизданный объект на панели слева, и он покажет вам график памяти, который часто может иметь четкие ссылочные циклы:

график отладки памяти

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

Иногда зная, какой объект хранит сильную ссылку, недостаточно, и вы действительно хотите знать, где в вашем коде была установлена ​​сильная ссылка. Опция "malloc stack", как показано в fooobar.com/questions/33524/..., может использоваться для определения того, что было в стеке вызовов, когда эта сильная ссылка была установлена ​​(часто позволяя вам идентифицировать точную строку кода, где эти сильные ссылки были установлены). Для получения дополнительной информации см. Видео WWDC 2016 Visual Debugging с Xcode.

Вы также можете использовать Инструменты для идентификации просочившегося объекта. Просто запустите приложение с помощью инструментов с помощью инструмента "Разделения" несколько раз (не один или два раза), возвращая приложение обратно в какое-то состояние стабильного состояния, и если память продолжает расти, тогда у вас, вероятно, будет сильный ссылочный цикл. Вы можете использовать инструмент "Выделения" для определения того, какие объекты не выпускаются, использовать функцию "отсчет количества записей", чтобы точно определить, где были установлены эти сильные ссылки, и т.д.

См. видео WWDC 2013 Устранение проблем с памятью и видео WWDC 2012 Производительность приложений iOS: память для ознакомления с проблемами идентификации и устранения проблем с памятью. Основные предлагаемые там технологии по-прежнему применимы сегодня (хотя инструменты пользовательского интерфейса инструментов немного изменились... если вы хотите ознакомиться с немного измененным пользовательским интерфейсом, см. Видео WWDC 2014 Улучшение вашего приложения с помощью инструментов).

В стороне, "сбор мусора" относится к совершенно другой системе памяти и здесь не применим.

Ответ 3

Используйте инструменты для проверки утечек и потери памяти. Используйте Mark Generation (Heapshot) в инструменте Allocations на инструментах.

Для того, чтобы использовать Heapshot для поиска памяти, см. блог bbum

В основном метод состоит в том, чтобы запускать инструменты, выделять инструмент, делать снимок, запускать итерацию вашего кода и повторять еще один кучей, повторяя 3 или 4 раза. Это будет указывать на память, которая выделяется и не выдается во время итераций.

Чтобы выяснить, какие результаты раскрываются, чтобы увидеть отдельные распределения.

Если вам нужно посмотреть, где сохраняются, выпускаются и автореализовываются для инструментов использования объекта:

Запуск в инструментах, в поле "Абонирование" задано значение "Запись отсчетов" (для Xcode 5 и ниже вы должны остановить запись, чтобы установить параметр). Причина, по которой приложение запускается, останавливает запись, разворачивается, и вы сможете увидеть, где все сохраняется, выпуски и автореализаторы.

Ответ 4

очень простой подход заключается в том, чтобы поместить печать в deinitialiser

deinit {
   print("<yourviewcontroller> destroyed.")
}

убедитесь, что вы видите, что эта строка печатается на консоли. поместите deinit во все ваши контроллеры view. в случае, если вы не смогли увидеть конкретный диспетчер view, это означает, что они являются ссылочным циклом. Возможные причины: делегирование является сильным, замыкания, фиксирующие self, таймеры, которые не являются invaidated, и т.д.

Ответ 5

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

Как только инструменты откроются, вы должны запустить свое приложение и выполнить некоторые взаимодействия, особенно в областях или контроллерах просмотра, которые вы хотите протестировать. Любая обнаруженная утечка будет отображаться как красная линия в разделе "Утечки". В представлении помощника есть область, в которой инструменты покажут вам трассировку стека, связанную с утечкой, давая вам информацию о том, где может быть проблема, и даже позволяя вам перейти непосредственно к нарушившемуся коду.