NSOperationQueue似乎挂起完成几秒钟
我有一个自定义视图控制器,实现从UITableViewDataSource
和UITableViewDelegate
协议。当我加载我的表的数据时(在我的viewDidLoad
方法中),我创建了一个NSOperationQueue
和一个NSInvocationOperation
并将其添加到队列中。我抛出一个活动指示器,并退出viewDidLoad
。NSOperationQueue似乎挂起完成几秒钟
用于该操作的方法结束活动指示器动画。
我注意到,当操作完成时,在操作真正完成之前有5-7秒的暂停,即使通过NSLog它看起来像操作的方法返回。
我试图用仪器找出停顿在哪里,但是我无法从中发现,因为我的大部分CPU时间都花在系统库中。
编辑 下面是一个简化版本:
@implementation MyViewController
@synthesize ...
- (void)viewDidLoad {
[super viewDidLoad];
self.opsQueue = [[NSOperationQueue alloc] init];
NSInvocationOperation *aiStartOp = [[[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(showActivityIndicators)
object:nil] autorelease];
[self.opsQueue addOperation:aiStartOp];
NSInvocationOperation *dataOp = [[[[NSInvicationOperation alloc]
initWithTarget:self
selector:@selector(dataUpdate)
object:nil] autorelease];
[dataOp addDependency aiStartOp];
[self.opsQueue addOperation:dataOp];
NSInvicationOperation *aiStopOp = [[[NSInvicationOperation alloc]
initWithTarget:self
selector:@selector(hideActivityIndicators)
object:nil] autorelease];
[aiStopOp addDependency:dataOp];
[self.opsQueue addOperation:aiStopOp];
}
/* other stuff */
@end
只要是明确的,在队列中的最后一个操作是这样的:
- (void)hideActivityIndicators {
DLog(@"hiding activity indicator");
self.portraitChartProgressView.hidden = YES;
[self.portraitChartProgressIndicator stopAnimating];
self.landscapeProgressView.hidden = NO;
[self.landscapeProgressIndicator startAnimating];
}
我在日志中看到的是输出上面的日志消息,然后是5秒的暂停,然后最后是隐藏指示器的视图。
任何想法?
需要在主线程上执行所有UI事件,绘图等。 您可以使用类似于以下内容的方式将呼叫转接到主线程。
- (void)hideActivityIndicators {
if (![NSThread isMainThread])
[self performSelectorOnMainThread:@selector(hideActivityIndicators) withObject:nil waitUntilDone:NO];
DLog(@"hiding activity indicator");
self.portraitChartProgressView.hidden = YES;
[self.portraitChartProgressIndicator stopAnimating];
self.landscapeProgressView.hidden = NO;
[self.landscapeProgressIndicator startAnimating];
}
EDIT”
现在我看起来更仔细,有一件事你可能并不需要做的是启动和停止‘加入到NSOperationQueue
装载’的意见。可能的在队列中唯一需要做的就是数据更新,然后发布通知和委托以在数据操作完成时更新视图。
示例项目TopSongs演示了这一点。主线程基于c在示例中的AppDelegate.m文件中。
是的,那是问题所在。但我现在好奇:如果所有UI更新都应该在主线程上执行,为什么他们不会抛出异常呢?他们为什么按预期执行,但只是延迟了5秒? – 2010-06-30 19:52:09
基本上,视图没有被重绘,以匹配从其他线程的视图对象上执行的状态更改,直到其他线程的运行循环被拆除。不是一个例外,而是一个并发问题。更多细节在这里http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html – falconcreek 2010-06-30 20:08:04
谢谢,它帮助我解决了类似的问题。 – negersiu 2010-11-25 14:12:19
您是否在主线程上调用hideActivityIndicators? – falconcreek 2010-06-30 18:33:59
@falconcreek:no;我是不是该? (请参阅编辑以更好地了解正在发生的事情) – 2010-06-30 18:39:52