当NSThread返回释放的对象?(苹果手机)

Ric*_*kiG 1 iphone memory-management nsthread

我有一个内存错误,似乎归结为一个线程中发生的事情.我在排除故障时遇到了困难.

我有一个UIViewController,当它处于活动状态时,即用户正在使用其视图时,从NSThread中的Web服务检索更新.

这是每3分钟完成一次,这个延迟由以下控制:

[self performSelector:@selector(timerDone) withObject:nil afterDelay:180.0];
Run Code Online (Sandbox Code Playgroud)

timerDone方法现在启动NSThread,它检索Web服务数据,并performSelector再次发送消息.这有点"检查更新,填充视图,关闭所有内容,重复"例程,工作得很好.

现在,用户当然可以突然点击一个按钮加载第二个UIViewController.当这发生时,我打电话给:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timerDone) object:nil];
Run Code Online (Sandbox Code Playgroud)

并在dealloc方法中进行清理.

我现在的问题是:如果NSThread正在运行,而用户更改了视图并启动了对象的解构,这是NSThread的起点,会发生什么?

我应该保持一个BOOL,告诉我NSThread是否仍然有效,如果是,那么如果是这样的话,如何处理NSThread.

线程是这样完成的:

- (void) runTimer {

    [self performSelector:@selector(timerDone) withObject:nil afterDelay:180];
}

- (void) timerDone {

    [self performSelector:@selector(runTimer) withObject:nil afterDelay:2];
    [NSThread detachNewThreadSelector:@selector(updateAllVisibleElements) toTarget:self withObject:nil]; 

    }

- (void) updateAllVisibleElements  {

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    //call approiate web service
    [pool release];
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*ier 7

这里有两个问题:首先,你正在performSelector:withObject:afterDelay:做一些NSTimer最好的事情(定期回调).cancelPreviousPerformRequestsWithTarget:selector:object:可能相当昂贵,而且由于你的线程可能会造成竞争条件.

第二个问题:每个线程都有自己的运行循环,并且两个机制(performSelector:...NSTimer)都绑定到当前线程的运行循环.

以下是我的建议:使用自己的显式运行循环创建一个长寿命的NSThread,以满足您的所有更新需求.请参阅" 线程编程指南",了解一些很好的示例代码.在那个帖子上,设置一个3分钟的重复NSTimer.每3分钟更新一次.

如果您需要在三分钟周期之外安排更新,那么您可以performSelector:onThread:withObject:waitUntilDone:用来拨打电话updateAllVisibileElements.我通常这样做的方法是将所有线程逻辑封装到单个对象(WebServiceController或其他)中.它创建自己的NSThread并将其保存在ivar中.然后我使用这样的代码:

- (void)requestUpdate
{
    if ([NSThread currentThread] != self.thread)
    {
        [self performSelector:@selector(update) onThread:self.thread withObject:nil waitUntilDone:NO];
        return;
    }
    else
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        //call approiate web service
        [pool drain];
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一点需要注意:你提到后台线程"填充视图".后台线程永远不应该调用UIKit.UIKit不是线程安全的,只应在主线程上调用.我通常通过将通知发布到视图控制器观察到的主线程来实现此目的."更新"对象不应该知道有关UI的任何信息.这破坏了Cocoa的模型 - 视图 - 控制器范例.