Подтвердить что ты не робот

Ошибка UIWebView EXC_BAD_ACCESS

У меня возникают сбои приложения, использующего UIWebView. Обычно это, когда страница не полностью загружена, и UIWebView отправляется селектором stopLoading. Или когда UIWebView полностью загружает страницу. У меня есть EXC_BAD_ACCESS. Стек выглядит следующим образом:

#0  0x95bb7688 in objc_msgSend
#1  0x30a671db in -[UIWebView webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
#2  0x3024a10d in __invoking___
#3  0x30249ff8 in -[NSInvocation invoke]
#4  0x358ab160 in HandleDelegateSource
#5  0x302452c1 in CFRunLoopRunSpecific
#6  0x30244628 in CFRunLoopRunInMode
#7  0x32044c31 in GSEventRunModal
#8  0x32044cf6 in GSEventRun
#9  0x309021ee in UIApplicationMain
#10 0x0000239c in main at main.m:13

для меня самая странная вещь: селектор webView:decidePolicyForNavigationAction:request:frame:decisionListener: отправлен в UIWebView, потому что такого селектора в документации UIWebView не существует! Только для Cocoa (не Cocoa touch) WebView. Я подозреваю, что что-то не так с UIWebView или его делегатом. Но я не могу установить точку останова, чтобы наблюдать за ними. Пожалуйста, сообщите, как я могу получить дополнительную информацию в этой ситуации.

4b9b3361

Ответ 1

Вам нужно прекратить загрузку webView и удалить делегат перед тем, как покинуть представление:

// ARC (correct solution)
- (void)dealloc {
    [_webView setDelegate:nil];
    [_webView stopLoading];
}

// non ARC
- (void)dealloc {
    [webView setDelegate:nil];
    [webView stopLoading];
    [webView release];
    [super dealloc];
}

// ARC (older solution)
- (void)viewWillUnload {
    [webView setDelegate:nil];
    [webView stopLoading];
}

В документации Apple говорится: Важно Перед выпуском экземпляра UIWebView, для которого вы установили делегат, вы должны сначала установить его свойство delegate равным nil. Это можно сделать, например, в методе dealloc.

Ответ 2

Попробуйте включить NSZombie и посмотреть, скоро ли что-то выпущено.

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

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

Ответ 3

View Will Disappear - это рабочая опция для принятого ответа:

// ARC
- (void)viewWillDisappear:(BOOL)animated{
    [self.webView setDelegate:nil];
    [self.webView stopLoading];
}

Это отлично работает для iOS 6.

Ответ 4

У меня был сбой EXC_BAD_ACCESS на прокручиваемом UIWebView, но только на iPad, и только когда пользователь оставил прокрутку UIWebView, когда он закрыл контроллер представления, содержащий его.

Установка делегата в nil не помогла решить мою проблему, но я нашел решение в другом месте по другой проблеме. Я добавил этот код к методу, который вызывается моей кнопкой закрытия:

for (id subview in webView.subviews){
        if ([[subview class] isSubclassOfClass: [UIScrollView class]]){
            [subview setContentOffset:CGPointZero animated:NO];
        }
    }

Это останавливает прокрутку до вызова метода dealloc, что, по-видимому, является проблемой.

Ответ 5

Я также видел эту точную ошибку, и она была вызвана делегатом, которого я назначил UIWebView, который не был сохранен (в моем случае UIViewController).

Ответ 6

Обработка отмены регистрации делегата из веб-браузера и остановка веб-просмотра при загрузке лучше всего обрабатывать с помощью метода dealloc ViewController.

В качестве примера, когда viewWillDisappear может выйти из строя:, если ViewController является дочерним элементом другого ViewController, вы можете инициировать удаление представления ViewController из родительского представления ViewController с помощью анимации. В то же время вы можете удалить ViewController из своего родителя и удалить его ссылку. В этот момент ViewController будет равен нулю, и viewWillDisappear никогда не будет вызван, то есть делегат WebView никогда не будет очищен.

Используйте dealloc и убедитесь, что ваш WebView всегда очищен.