UIWebView EXC_BAD Access
Hy
I've got a UIView. In one method, I alloc a WebView, and set it's to a retain property.
self->webView= [[UIWebView alloc] initWithFrame:self.frame];
Then I start to load a HTML string. After it's loaded, I resize the view and start a callBack to the superview to resize. It's working. My problem is that, if the user go back before the view has been loaded, the view's are released. Then my WebView throw a BAD_ACCESS. Here is the dealloc method:
-(void)dealloc{
[self.webView setDelegate:nil];
[self.webView stopLoading];
[self setWebView:nil];
[htmlStr release];
[super d开发者_StackOverflow社区ealloc];}
The callback trace is shown in the screenshot. The interesting is that, if I don't release the WebView it is work's like the charm. If I release the WebView, then when it's deallocated, I get an error message in the log:
![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]
EDIT: It has been fixed. It turns out, that my image loading method was guilty. I've start a new thread (NSOperationQueue and NSInvocationOperation in that) to load an image, and make a performSelectorOnMainThred: when it's finished. Whit that, I've loaded more than hundred small (1-2 KB) image, on every page switch, which was a really big overhead. When I wrote a method which download the images in one thread one by one, this bug has never came again
You are modifying UI from other tread than main. This is forbidden as UIKit is not thread-safe (hence the crash...). If you want to modify the UI from another thread, you must use:
performSelectorOnMainThread:withObject:waitUntilDone:
Other thing I've notice in your code is that you incorrectly release your properties in -dealloc
. You should not use synthesized setters like this:
[self setWebView:nil]; // same as self.webView = nil;
You should not, because it can bring you lots of problems if you start using KVO (Key-Value Observing) on you properties... Instead just write:
[webView release];
or, if you want to avoid "The Heisenbug":
[webView release], webView = nil;
EDIT: you can also benefit from answer to this SO question: How to safely shut down a loading UIWebView in viewWillDisappear?
Dont call it with self.webView
in dealloc, just use webView
:
- (void)dealloc {
if ([webView isLoading])
[webView stopLoading];
[webView setDelegate:nil];
[webView release], webView = nil;
[super dealloc];
}
It has been fixed. It turns out, that my image loading method was guilty. I've start a new thread (NSOperationQueue and NSInvocationOperation in that) to load an image, and make a performSelectorOnMainThred: when it's finished. Whit that, I've loaded more than hundred small (1-2 KB) image, on every page switch, which was a really big overhead. When I wrote a method which download the images in one thread one by one, this bug has never came again.
精彩评论