Массовая утечка памяти в ios UIWebView
В поисках утечек памяти в других местах нашей системы я создал веб-страницу объемом 20 МБ с мета-тегом обновления. Идея состояла в том, чтобы переместить много данных через наш код данных, чтобы подтвердить стабильность памяти.
<html>
<meta http-equiv="refresh" content="1">
<body>
<div style="border: 1px solid red">
Content loading
</div><!-- 20mb worth of comments -->
</body>
</html>
то, что я обнаружил, было uiwebview, показывающим, что страница метаобновления очень и очень быстро теряет память. память приложения достигает 300 МБ примерно за 2 минуты и снимается с предупреждением о низкой памяти, даже когда наш код не находится в игре.
Я остановил загрузку обновлений и попытался удалить веб-просмотр.
Я пробовал loadurl:"about:blank", loadhtml:"", закрытие документа javascript.
Я также попытался написать рекурсивный метод removeFromSuperview и removeFromParentViewController, считая, что частное представление прокрутки в веб-представлении является проблемой памяти, но эта память никогда не освобождается. Кажется, я не могу найти надежный способ закрыть веб-просмотр, когда мы закончим с ним.
Мы жили с медленной скоростью просачивания веб-просмотра в течение достаточно долгого времени и действительно хотим найти способ гарантировать, что веб-просмотр может быть полностью очищен, когда мы закончим с ним. Недавно мы конвертировали приложение в ARC, которое не меняло частоту памяти.
Я подумываю попробовать рекурсивный цикл по всем объектам в веб-просмотре и посмотреть, можно ли их освободить. Instruments показывает 20 МБ cfdatas, живой, для каждого обновления страницы 20 МБ, но не показывает их как утечки. если я только доставляю заголовок ответа и выполняю его клиенту urlprotocol, то мы работаем стабильно, поэтому было бы достаточно подтвердить mem leaks в оставшейся части пути к данным, но это такой впечатляющий результат теста, который я надеюсь найти решение для утечки памяти webview однажды и для всех.
У кого-нибудь есть идеи получше, или кто-то пытался вернуться через объекты в uiwebview?
4 ответа
Я избавился от утечки памяти в моем UIWebView, установив его HTML в пустую строку. Единственное место, где это можно сделать, это когда контроллер представления, содержащий веб-представление, исчезает:
- (void) viewWillDisappear:(BOOL)animated {
if (self.isMovingFromParentViewController) {
[self.wv loadHTMLString: @"" baseURL: nil];
}
}
Крик всем разработчикам: Реализация didReceiveMemoryWarning абсолютно необходима при использовании UIWebView!
И это особенно важно, когда UIWebView может перемещаться в любое место или на страницу, которую вы знаете, что приводит к огромным утечкам в UIWebView, например, m.youtube.com.
Отличный и обычно простой способ исправить утечки - это просто перезагрузить страницу. Таким образом, вам не нужно заботиться о том, чтобы страница стала пустой, и обычно пользователь сможет продолжить свою работу с того места, где он остановился.
В вашем контроллере представления переопределите didReceiveMemoryWarning следующим образом:
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
[myWebView reload];
}
С iOS 8 и выше вам действительно повезло. WKWebView
не протекает и имеет гораздо меньший объем памяти, чем UIWebView
, Протестировав его с загруженными изображениями веб-страницами, содержащими сложный Javascript, он показал хорошие результаты
Справочник по классу Apple WKWebView
Это не идеально, хотя. Тогда снова, надеюсь, недостатки будут решены вовремя. Ознакомьтесь с советами Синго Фукуямы на GitHub:
- Слабое "я" в блоках.
Это было одной из важных причин, которые приводят к задержке памяти WebView даже при отключении стека навигации.