Reputation: 26336
Is dealloc
guaranteed to be called on the same thread that created a NSObject
instance? For example, if I call [[MyFluffyBunny alloc] init]
on the main thread, is dealloc
guaranteed to also be called on the main thread, or can it be called on any thread once MyFluffyBunny
is no longer retained?
I see sporadic crashes in my app that points to that it's not guaranteed, but I've been unable to find any documentation confirming it.
Upvotes: 8
Views: 2871
Reputation: 90581
The object is deallocated on whatever thread releases the last strong reference to it. That is, whatever thread calls -release
the final time. It is actually during that -release
call that the object is deallocated.
The documentation for the -release
method in the NSObject
protocol says:
Decrements the receiver’s reference count. … The receiver is sent a
dealloc
message when its reference count reaches 0.
The Advanced Memory Management Programming Guide: Practical Memory Management article includes this among the reasons to not use -dealloc
to manage scarce resources:
Cleanup logic being executed on the wrong thread.
If an object is autoreleased at an unexpected time, it will be deallocated on whatever thread’s autorelease pool block it happens to be in. This can easily be fatal for resources that should only be touched from one thread.
Upvotes: 16
Reputation: 31016
There is no such guarantee and, in fact, it makes for some subtle bugs when using KVO (and bindings on OS X).
You can see it in action fairly easily by creating an object that logs [NSThread currentThread]
during init
and dealloc
, then running code such as:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
Testing *testing = [[Testing alloc] init];
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
NSLog(@"Use testing in background: %@", testing);
});
testing = nil;
return YES;
}
Upvotes: 2
Reputation: 2989
I'm unaware of a line in the documentation that says anything about this, but here are some points of logic:
If you can't find a guarantee somewhere, assume it doesn't exist. (It sounds like you're aware of this already, and are hoping beyond hope that somebody else can point you to something that gives you the answer you want)
That requirement cannot be possible because you can construct something on a thread, then end that thread, then have the last reference go out of scope somewhere else in some other thread. It wouldn't be possible at this point to dealloc
on the old thread because it no longer exists.
Upvotes: 1