views:

253

answers:

3

Is it an error to call dealloc on a UIViewController from a background thread? It seems that UITextView (can?) eventually call _WebTryThreadLock which results in:

bool _WebTryThreadLock(bool): 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.

Background: I have a subclassed NSOperation that takes a selector and a target object to notify.

-(id)initWithTarget:(id)target {
   if (self = [super init]) {
      _target = [target retain];
   }
   return self;
}

-(void)dealloc {
   [_target release];
   [super dealloc];
}

If the UIViewController has already been dismissed when the NSOperation gets around to running, then the call to release triggers it's dealloc on a background thread.

+3  A: 

The simple rule is that it's an error to do anything on a UI* from a background thread.

David Gelhar
What about `performSelectorOnMainThread`? Is this documented anywhere? All I've seen is rather vague references to "don't manipulate UI in background thread" - which is a lot less restrictive than your *anything*.
Mark Brackett
It's the normal way to call performSelectorOnMainThread: if you want to manipulate the UI from a background thread.
schaechtele
@schaechtele - Are you calling [UIViewController performSelectorOnMainThread:], or [self performSelectorOnMainThread:] when you do a cross-thread call from a different object?
Mark Brackett
I think, that performSelectorOnMainThread: can be called on an object only, means, is no class-method. So you have to call it on self (or another object).
schaechtele
+2  A: 

The second post here had useful info, but their answer didn't work for me.

http://tech.efreedom.com/Question/1-945082/UIWebView-in-multithread-ViewController

It also seems that this may have been addressed in iPhone OS 4, but not sure.

I ended up not releasing my UIWebView in the controller's dealloc when [NSThread isMainThread] was NO. Would rather leak than crash (until I get a better solution).

Jason
Yep - same problem. I solved it by just doing the release on the main thread, but sutorekease would work as well, I suppose.My main concern is whether it's expected behavior or not In ObjC. I should check iPhone 4 to see if it's changed - which would at least give some indication that it's a bug.
Mark Brackett
I think this is "fixed" in iOS4, at least based on cursory testing
Jason
+1  A: 

It is an error to call dealloc on anything at any time. You should only ever call release.

You should not access any UI related instances from a background thread. This includes using getter methods because they may modify things internally. However, retain and release are thread safe for any object at any time, as long as the normal rules for retain and release are followed. UI related instances include any object that is referenced by an active UIView or UIViewController.

performSelectorOnMainThread does not do anything more than retain an object until it gets to the main thread. It is safe to call on any UI related object.

drawnonward
Right. I only call release, but since it's the last release it ends up calling dealloc internally. If release is thread agnostic, then it follows that dealloc must be as well - right? So, is _WebTryThreadLock just a (possibly buggy) exception to the rule?
Mark Brackett