Как исследовать утечки памяти в ios? - PullRequest
0 голосов
/ 04 марта 2019

Я создал простой поток для проверки памяти в приложении 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 в коде.Проверяя утечки в Instruments , я получил следующий график:

enter image description here

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

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

enter image description here

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

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

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

Сильный против слабого против неизвестного -

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

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

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

То, что является циклом сохранения:

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

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

Теперь давайте посмотрим, что у вас есть, вы используете UINavigationController & segue, а UINavigationController - этостек LIFO, также в соответствии с apple

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

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

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

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

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

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

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

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

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

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

0 голосов
/ 04 марта 2019

Перейти к Edit Scheme -> Run -> Diagnostics Теперь отметьте Malloc stack, как на скриншоте.Memory debug config После этого перестройте и запустите.Теперь откройте Debug memory graph, вы увидите фиолетовый значок в списке вашего класса, где произошла утечка памяти.см. этот снимок экрана Memory Debug Graph Пример Репо с утечкой памяти Swift Demo Memory Demo Вот представление об утечке памяти с реальным примером с прикрепленным репо Real Example picture with memory leak Вы можете выполнить ту же процедуру в своем проекте, чтобы определить утечку памяти

...