Hi I'm usuing [NSThread detachNewThreadSelector:toTarget:withObject:] and I'm getting 开发者_如何学运维a lot of memory leaks because I have no autorelease pool set up for the detached thread. I'm just wondering where I actualy do this? Is it before I call
[NSThread detachNewThreadSelector:toTarget:withObject:]
or in the method that is being ran in the other thread?
Any help would be appreciated, some sample code would be great.
Thanks.
in the method you call with the thread... i.e. given this...
[NSThread detachNewThreadSelector:@selector(doStuff) toTarget:self withObject:nil];
Your method would be...
- (void)doStuff {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Do stuff
[pool release];
}
You have to set up an autorelease pool in the method you call and that will be executed in the new detached thread.
For example:
// Create a new thread, to execute the method myMethod
[NSThread detachNewThreadSelector:@selector(myMethod) toTarget:self withObject:nil];
and
- (void) myMethod {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Here, add your own code
// ...
[pool drain];
}
Note that we use drain and not release on the autoreleasepool. On iOS, it has no difference. On Mac OS X, if your app is garbage collected, it will triggers garbage collection. This allows you to write code that you can re-use more easily.
Create the new thread:
[NSThread detachNewThreadSelector:@selector(myMethod) toTarget:self withObject:nil];
Create the method that is called by the new thread.
- (void)myMethod
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Your Code
[pool release];
}
What if you need to do something to the main thread from inside your new thread (for example, show a loading symbol)? Use performSelectorOnMainThread.
[self performSelectorOnMainThread:@selector(myMethod) withObject:nil waitUntilDone:false];
Refer :- iPhone SDK Examples
Do it in the method you call. Essentially, you should set up the method that gets called as a self-contained work unit (in fact, it will then be compatible with being called through either [NSOperation][1]
or Grand Central Dispatch, too: both better ways of organising concurrent work).
But what if I can't change the implementation of the method I'm calling on a new thread?
In that case, you would go from doing this:
[NSThread detachNewThreadSelector: @selector(blah:) toTarget: obj withObject: arg]
to doing this:
[NSThread detachNewThreadSelector: @selector(invokeBlah:) toTarget: self withObject: dict]
- (void)invokeBlah: (id)dict {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id obj = [dict objectForKey: @"target"];
id arg = [dict objectForKey: @"argument"];
[obj blah: arg];
[pool release];
}
rather than using the dictionary, you could also create an NSInvocation that encapsulates the remote object call. I just chose a dictionary because it's the quickest way to show the situation in a SO answer. Either would work.
The documentation states that the method run in the thread must create and destroy its own autorelease pool. So if your code has
[NSThread detachNewThreadSelector:@selector(doThings) toTarget:self withObject:nil];
The method should be
- (void)doThings {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Do your things here
[pool release];
}
精彩评论