Случайные сбои происходят в моем проекте iphone, видят два стека вызовов, все в веб-ядре, все сбои после освобождения UIWebView - PullRequest
1 голос
/ 26 марта 2012

Случайные сбои происходят в моем проекте iphone, видят два стека вызовов, все в веб-ядре, все сбои после освобождения UIWebView.

См. Сбой 1, кажется, веб-ядро не может полностью его закрыть, заблокировано ли оно другими запущенными потоками?

См. Сбой 2, почему он по-прежнему сталкивается с некоторыми проблемами, даже если UIWebView был выпущен?

Любая идея или обсуждение будет оценено, спасибо заранее.

Сбой 2 имеет более высокую воспроизводимую частоту, чем сбой 1, сканируйте исходный код WebCore, кажется, кэш манифеста был удален (кто это сделал?) При попытке получить к нему доступ.

web core crash 1

web core crash 2

Ответы [ 2 ]

0 голосов
/ 26 марта 2012

Перед выпуском веб-просмотра попытайтесь сбросить делегата при остановке загрузки.

[webView stopLoading];
webView.delegate = nil;
[webView release];
webView = nil;
0 голосов
/ 26 марта 2012

Я предполагаю, что вы устанавливаете некоторый объект (возможно, ваш контроллер представления) в качестве делегата вашего webView, либо через Interface Builder, либо через код, который выглядит примерно так:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.webView.delegate = self;
}

- (void)dealloc
{
    [self.webView release];
    [super dealloc];
}

В этом коде есть серьезная ошибка, которая не сразу очевидна, если вы не знаете, что искать. Вы можете это заметить?

Когда контроллер получает dealloc'd, он выпускает веб-представление, но это не обязательно означает, что веб-представление больше не существует. Это может все еще быть сохранено некоторым кодом внутри его внутренней реализации, и это может все еще загружать контент.

Когда загрузка завершится, веб-представление вызовет метод, подобный webViewDidFinishLoad:, для своего делегата. Проблема в том, что ваш контроллер представления был делегатом, а ваш контроллер представления больше не существует. Раздел памяти, в котором использовался контроллер представления, был восстановлен операционной системой и больше не доступен для вашего процесса приложения. Хотя веб-представление этого не знает. У него все еще есть ссылка на этот адрес памяти в свойстве делегата. Поэтому он пытается вызвать метод делегата для этого объекта, и к сожалению ... EXC_BAD_ACCESS.

Подобные сбои выглядят случайными, поскольку они зависят от того, что ваше приложение делает в фоновом режиме в данный момент. Это делает их сложным для диагностики. К счастью, их легко решить. Просто установите делегат объекта равным nil до того, как вы отпустите его в свой оператор dealloc, например:

- (void)dealloc
{
    self.webView.delegate = nil;
    [self.webView release];
    [super dealloc];
}

Задавая делегату веб-представления значение nil до его освобождения, вы гарантируете, что веб-представление не будет пытаться вызывать методы делегата для вашего объекта после его освобождения.

Если вы используете ARC, у вашего класса может не быть метода dealloc. Обычно это нормально, но в таком случае вы должны добавить его. Вы не хотите вызывать release, если используете ARC, но вам все равно следует добавить метод dealloc и установить для свойства делегата значение nil.

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

...