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)
这里有两个问题:首先,你正在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的模型 - 视图 - 控制器范例.
归档时间: |
|
查看次数: |
1531 次 |
最近记录: |