开发者

performSelectorOnMainThread throws message deallocated

While parsing of the twitter data, I used threads to call the main URL to download the data. It does the downloading perfectly but when I hit the back button while the data is downloading it throws performSelectorOnMainThread message deallocated. I know we can use isCancelled but its not working for me yet. Does anyone have come across this issue and have resolved it.

- (void)LoadTwitterData
{
NSString *urlString =@"http://search.twitter.com/search.json?q=tabc&result_type=recent&rpp=2500";
NSURL *url = [NSURL URLWithString:urlString];

NSString *jsonString = [NSString stringWithContentsOfURL:url];
NSDictionary *values = [jsonString JSONValue];    

/**** Throws here *****/
[self performSelectorOnMainThread:@selector(didFinishLoadingResults:) withObject:values开发者_StackOverflow waitUntilDone:NO];

}


If you spin off a thread using a selector on self, you need to make sure that self is retained for the duration of that thread, otherwise (as in your case) self can be deallocated and your thread will try to call back into a zombie. The easiest way to do this is to pass self to the thread as an argument. If you use performSelectorInBackground:withObject: you should do something like this:

[self performSelectorInBackground:@selector(LoadTwitterData) withObject:self];

Or if you use NSThread you should pass self to the object: initializer argument.

In fact the safest way to use thread methods is to make the method static like this:

+ (void)LoadTwitterData:(id)arg
{
    // ...
    MyController *self = arg;

    // ... do work

    [self performSelectorOnMainThread:@selector(didFinishLoadingResults:)
                           withObject:values waitUntilDone:NO];

}

This way you are unable to access instance variables by accident which avoids various multi-threading issues. Any and all data the thread needs, including the self to callback to, should be passed in as 'arg', which can be an array or dictionary or whatever you need. This way you know that everything the thread needs will be retained for the duration of the thread, and because you aren't accessing instance variables through self, another thread can't go and change them around underneath you.

Another thing you should do in a thread method is wrap the whole thing with an autorelease pool:

- (void)LoadTwitterData
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    @try {
        // ...
    } @finally {
        [pool drain];
    }
}


If LoadTwitterData: is in a background thread, you need to create an Auto release pool (If you haven't already). Surround your code with-

NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];


//your code

[pool drain];
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜