performSelectorOnMainThread抛出已释放的消息

时间:2011-10-12 14:14:55

标签: iphone objective-c synchronization

在解析twitter数据时,我使用线程调用主URL来下载数据。它完美地进行了下载,但是当我在下载数据时按下后退按钮时,会抛出performSelectorOnMainThread消息被释放。我知道我们可以使用isCancelled,但它还没有为我工作。有没有人遇到过这个问题并且已经解决了。

- (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 waitUntilDone:NO];

}

2 个答案:

答案 0 :(得分:2)

如果使用self上的选择器分离线程,则需要确保在该线程的持续时间内保留self,否则(如在您的情况下){{1}可以解除分配,你的线程将尝试回调成僵尸。最简单的方法是将self作为参数传递给线程。如果你使用self,你应该这样做:

performSelectorInBackground:withObject:

或者,如果您使用[self performSelectorInBackground:@selector(LoadTwitterData) withObject:self]; ,则应将NSThread传递给self初始值设定项参数。

事实上,使用线程方法最安全的方法是使方法保持静态,如下所示:

object:

这样您就无法偶然访问实例变量,从而避免了各种多线程问题。线程需要的任何和所有数据,包括要回调的+ (void)LoadTwitterData:(id)arg { // ... MyController *self = arg; // ... do work [self performSelectorOnMainThread:@selector(didFinishLoadingResults:) withObject:values waitUntilDone:NO]; } ,都应该作为'arg'传递,它可以是数组或字典,也可以是你需要的任何东西。通过这种方式,您知道线程所需的所有内容都将在线程的持续时间内保留,并且由于您没有通过self访问实例变量,因此另一个线程无法在您下面更改它们。

你应该在一个线程方法中做的另一件事是用自动释放池包装整个东西:

self

答案 1 :(得分:0)

如果LoadTwitterData:位于后台线程中,则需要创建自动发布池(如果尚未创建)。用 -

包围你的代码
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];


//your code

[pool drain];