Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Ugly as hell workaround for UIWebView crashing on non-main thread dealloc (inside a UIView)
- (void)dealloc {
webView_.delegate = nil; // delegate is self here, so first set to nil before call stopLoading.
[webView_ stopLoading];
// UIWebView must be released in the main thread, or we get:
// 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...
// This is less evil than the proposed
// Calling removeFromSuperview in a dealloc is ugly and evil, but else UIView has a strong reference to UIWebView and our main-release call would be irrelevant.
if (![NSThread isMainThread]) {
[webView_ performSelectorOnMainThread:@selector(removeFromSuperview) withObject:nil waitUntilDone:YES];
[webView_ performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:YES];
[super dealloc];

@nselvis - if i call stopLoading first, couldn't this maybe lead to calling one of my delegate methods within the dealloc? (if the dealloc is on another thread and then context switches...)?


After @anlumo1 'es suggestion, performSelectorOnMainThread immediately calls release if already on main thread, when waitUntilDone is set to YES. (

Still unsure about that removeFromSuperview.

Also - how would I solve this in ARC?

On ARC: maybe settings webView_ to nil in main thread will just work? Something like

dispatch_sync(dispatch_get_main_queue(), ^() {
        webView_ = nil;

@insanehunter problem is that the block will hold a strong reference to it, so in the end webView will get deallocated in the thread the block was created. (i tried that at first)

Oh, that's really tricky then.

__block variables are not retained, so probably this code should work?

__block id this = self;
dispatch_sync(dispatch_get_main_queue(), ^() {
      this.webView_ = nil;

Anyway, I should go and read on blocks and GCD.


__block will be retained under ARC - Apple changed this behavior. I could use __weak, but that's more overhead, and I'm not sure what other implications this might would have. (or __unsafe_unretained combined with a CFRetain/CFRelease? feels very hacky...)

Super thanks man.. You saved my a**..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment