Как исследовать утечки памяти в ios?

Я создал простой поток для проверки памяти в приложении ios. У меня есть два контроллера представления в стеке навигации. Я показываю предупреждение в первом контроллере представления, чтобы пользователь мог перейти к следующему. Ниже приведен код, который я использую.

class ViewController: UIViewController {

    @IBOutlet weak var labelInfo: UILabel!

    override func viewDidLoad() {
       super.viewDidLoad()

    }

    @IBAction func showNextScreen(_ sender: Any) {

        let alert = UIAlertController(title: "Alert", message: "Go to next screen?", preferredStyle: .alert)

        alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { [unowned self] (action) in

            self.performSegue(withIdentifier: "showNextScreen", sender: nil)

        }))

        alert.addAction(UIAlertAction(title: "No", style: .default, handler: { [unowned self] (action) in

            self.labelInfo.text = "You did not move to next screen"
            alert.dismiss(animated: true, completion: nil)

        }))

        self.present(alert, animated: true, completion: nil)

    } 

}

Изучив ресурсы, в которых упоминается, что не должно быть сильного цикла ссылок, я использовал в коде unowned self. Проверив утечки в Инструментах, я получил следующий график.

введите здесь описание изображения

На графике нет утечек, что обозначено зелеными галочками. Однако по мере того, как я перемещаюсь между двумя контроллерами представления, график использования памяти увеличивается. Что может быть причиной такого увеличения использования памяти (первый вопрос)?

Затем я также проверил эффект замены неизвестного себя на самого себя. Результат у меня такой же, как и раньше. Это говорит о том, что нет сильной ссылки. Как мы определяем наличие сильного цикла удержания со ссылкой на этот пример (второй вопрос)?

введите здесь описание изображения


person Sujal    schedule 04.03.2019    source источник
comment
как ты вернешься со 2-го ВК   -  person Mohmmad S    schedule 04.03.2019
comment
@MohmmadS Я использую кнопку «Назад» навигационного контроллера.   -  person Sujal    schedule 04.03.2019
comment
@Sujal использует навигационный контроллер?   -  person Mohmmad S    schedule 04.03.2019
comment
Для меня самый простой и самый быстрый способ увидеть, освобождаются ли контроллеры представления, — это поместить строку печати в deinit. В моих проектах у меня есть класс BaseViewController, который вызывает метод Utils.debugPrint("\(self) deinitialized") в deinit. И все мои VC являются подклассами.   -  person Au Ris    schedule 04.03.2019


Ответы (2)


Начиная со второго вашего вопроса.

Помимо инструментов, ваш код переходит к UIViewController и отбрасывает его, если это так просто, давайте пока не будем думать о циклах сохранения.

Сильный, слабый или неуправляемый

1- Обычно при создании свойства ссылка является сильной, если они не объявлены слабыми или не принадлежащими.

2- Если свойство помечено как слабое, оно не будет увеличивать счетчик ссылок.

3- Ссылка без владельца находится между ними, они не являются ни сильными, ни необязательными. Компилятор предположит, что объект не освобождается, поскольку сама ссылка остается выделенной.

Что такое цикл сохранения:

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

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

Теперь давайте посмотрим, что у вас есть, вы используете UINavigationController & segue, а UINavigationController — это стек LIFO, также согласно яблоко

Контроллер навигации — это контейнерный контроллер представления, который управляет одним или несколькими дочерними контроллерами представления в интерфейсе навигации. В этом типе интерфейса одновременно виден только один дочерний контроллер представления.

Поэтому, проверяя вашу функцию UIViewController deinit, я думаю, у вас не возникнет проблем с тем, что ссылка освобождена.

Теперь давайте попробуем найти что-то еще в UIAlertAction у вас есть этот [unowned self].

Когда использовать бесхозное или слабое "я"

Единственный случай, когда вы действительно хотите использовать [непринадлежащее себе] или [слабое я], — это когда вы хотите создать сильный референтный цикл. Цикл сильной ссылки — это когда существует цикл владения, когда объекты в конечном итоге владеют друг другом (возможно, через третье лицо), и поэтому они никогда не будут освобождены, потому что они оба гарантируют, что друг друга будут поддерживать.

В конкретном случае закрытия вам просто нужно понять, что любая переменная, на которую есть ссылка внутри него, становится «принадлежностью» закрытия. Пока существует закрытие, эти объекты гарантированно будут рядом. Единственный способ остановить это владение — это сделать [невладеющее собой] или [слабое я]. Таким образом, если класс владеет замыканием, и это замыкание фиксирует сильную ссылку на этот класс, то у вас есть сильный цикл ссылок между замыканием и классом. Это также включает в себя, если класс владеет чем-то, что владеет закрытием.

И, как вы сказали, переключение [unowned self] и [self] ничего не дало.

Теперь первый вопрос,

Проверки утечки инструментов просты: просто сравните значительное увеличение памяти за определенный период времени и сравнивайте все это друг с другом в зависимости от того, что происходит, это не 100% описание, но близко, поэтому всякий раз, когда появляется эта зеленая галочка вверх означает, что вы прошли тест. это еще не означает, что вы в безопасности на 100%, вы можете визуально увидеть распределение в нижней части прибора, наблюдать за изменениями значений (увеличение/уменьшение) .. если что-то увеличивается, не уменьшаясь, Я думаю, вы нашли свою проблему.

Глядя на ваш случай, я не думаю, что вы найдете его

person Mohmmad S    schedule 04.03.2019
comment
Добавив аналогичный код alertcontroller во второй viewcontroller, я смог получить разницу, используя self, unowned self. И я также мог сгенерировать случай, когда инструменты не показывали утечек, но выделение объектов увеличивалось (imgur.com/a/Ys1D6QF) Я думаю, что в моем предыдущем коде, поскольку мой начальный контроллер представления не деинициализируется, я не смог увидеть эффект. - person Sujal; 09.03.2019

Перейдите к Edit Scheme -> Run -> Diagnostics Теперь отметьте Malloc stack, как показано на скриншоте. Конфигурация отладки памяти После этого пересоберите и запустите . Теперь откройте Debug memory graph, вы увидите фиолетовую иконку в списке вашего класса, где произошла утечка памяти. посмотрите этот скриншот Memory Debug Graph Пример репозитория с утечкой памяти: Демонстрация Swift Memory Leak Вот представление об утечке памяти на реальном примере с прикрепленным репозиторием Реальный пример изображения с утечкой памяти Вы можете выполнить ту же процедуру в своем проекте, чтобы определить утечка памяти

person Md. Sulayman    schedule 04.03.2019