UIWebView EXC_BAD Access - PullRequest
       29

UIWebView EXC_BAD Access

1 голос
/ 08 сентября 2011

Hy

У меня есть UIView. В одном методе я выделяю WebView и устанавливаю для него свойство retain.

    self->webView= [[UIWebView alloc] initWithFrame:self.frame];

Затем я начинаю загружать строку HTML. После его загрузки я изменяю размер представления и запускаю callBack для суперпредставления, чтобы изменить размер. Работает. Моя проблема в том, что, если пользователь вернется до того, как представление будет загружено, представления будут освобождены. Тогда мой WebView бросить BAD_ACCESS. Вот метод dealloc:

-(void)dealloc{
[self.webView setDelegate:nil];
[self.webView stopLoading];  
[self setWebView:nil];
[htmlStr release];
[super dealloc];}

Трасса обратного вызова показана на скриншоте. Интересно то, что, если я не выпущу WebView, это будет похоже на шарм. Если я освобождаю WebView, то когда он освобождается, в журнале появляется сообщение об ошибке:

 ![bool _WebTryThreadLock(bool), 0x4e05150: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...][1]

РЕДАКТИРОВАТЬ: это было исправлено. Получается, что мой метод загрузки изображения был виновен. Я начал новый поток (NSOperationQueue и NSInvocationOperation в этом), чтобы загрузить изображение, и сделать executeSelectorOnMainThred: когда он закончится. Тем не менее, я загружал более ста маленьких (1-2 КБ) изображений на каждом переключателе страниц, что было очень большой нагрузкой. Когда я написал метод, который загружал изображения в один поток один за другим, эта ошибка больше никогда не появлялась

Ответы [ 3 ]

1 голос
/ 08 сентября 2011

Вы изменяете пользовательский интерфейс с другого протектора, кроме основного.Это запрещено, поскольку UIKit не является потокобезопасным (следовательно, сбой ...).Если вы хотите изменить пользовательский интерфейс из другого потока, вы должны использовать:

performSelectorOnMainThread:withObject:waitUntilDone:

Еще одна вещь, которую я заметил в вашем коде, это то, что вы неверно высвобождаете свои свойства в -dealloc.Вы не должны использовать синтезированные сеттеры, как это:

[self setWebView:nil];  // same as self.webView = nil;

Вы не должны, потому что это может принести вам много проблем, если вы начнете использовать KVO (Key-Value Observing) в своих свойствах ... Вместо этого просто напишите:

[webView release];

или, если вы хотите избежать "Гейзенбаг" :

[webView release], webView = nil;

РЕДАКТИРОВАТЬ: вы также можете воспользоватьсяОтвет на этот вопрос SO: Как безопасно завершить загрузку UIWebView в viewWillDisappear?

0 голосов
/ 09 сентября 2011

Это было исправлено. Получается, что мой метод загрузки изображения был виновен. Я начал новый поток (NSOperationQueue и NSInvocationOperation в этом), чтобы загрузить изображение, и сделать executeSelectorOnMainThred: когда он закончится. Тем не менее, я загружал более ста маленьких (1-2 КБ) изображений на каждом переключателе страниц, что было очень большой нагрузкой. Когда я написал метод, который загружал изображения в один поток один за другим, эта ошибка больше никогда не возникала.

0 голосов
/ 08 сентября 2011

Не вызывайте его с self.webView в dealloc, просто используйте webView:

- (void)dealloc {
    if ([webView isLoading])
        [webView stopLoading];
    [webView setDelegate:nil];
    [webView release], webView = nil;
    [super dealloc];
}
...