我正在尝试解决围绕NSTimer / NSOperationQueue执行不一致的UI问题。我看到无论我是否使用NSTimer或NSInvocationOperation来触发下面的代码,很多时候性能都是需要的,但是几次行为很慢(并且如下例所示,代码运行时间超过1秒) )。
这是我通过NSInvocationOperation调用的代码:
-(void) progressAsynch{
for (count = 1; count<=100; count++) {
// Reposition Label's CGRect.
[self performSelectorOnMainThread:@selector(moveLabelToNewPosition) withObject:nil waitUntilDone:YES];
//Update the progress of the progress view
[self performSelectorOnMainThread:@selector(advanceProgressViewProgress) withObject:nil waitUntilDone:YES];
//Sleep for 10 millisecs
[NSThread sleepForTimeInterval:0.01];
//if the progress view has progressed fully call main thread to to next tasks.
if(progressView.progress == 1) {
[self performSelectorOnMainThread:@selector(processResult) withObject:nil waitUntilDone:YES];
}
}
}
NSTimer调用的方法代码(每10毫秒触发一次)与上面非常相似,只是它不会有for循环。
显然,这种处理之外的某些内容似乎经常会降低这种性能。
很想知道你是否遇到类似的问题,或者你是否有任何可能帮助我的指针/花絮。
提前致谢..
答案 0 :(得分:0)
线程间通信速度不快,waitUntilDone:YES
增加了额外的线程同步开销,完全没必要(我非常确定performSelectors是序列化的)。你可能会有更好的运气,比如
-(void) progressAsynch{
for (count = 1; count<=100; count++) {
[self performSelectorOnMainThread:@selector(stuff) withObject:nil waitUntilDone:NO];
[NSThread sleepForTimeInterval:0.01];
}
}
然而,这仍然不好。看起来self
是一个视图或视图控制器,它将由NSInvocation保留,并且可能在后台线程上发布。 UIKit的大多数都不是线程安全的; Game Center示例代码转到伟大的长度,表明UIKit类甚至不应该在后台线程上发布,因为发布可能会导致-dealloc
,这在UIKit类中可能不是线程-安全。 (哎哟。)
(另请注意,您对progressView.progress
的调用对后台线程并不安全。)
你也处于可能的极限:我很确定iOS时间片是10毫秒,这意味着如果其他任何东西需要CPU(并且有很多后台进程;请尝试使用在某些时候仪器中的活动监视器)您的动画可能看起来滞后。
最后,通过一些音频播放代码,我们注意到NSTimer不是很准确。我不知道为什么。我认为我们用一些使用SIGALRM的东西(以及可能不信号安全,感叹的代码)来修复它。
您可能会更好地使用CADisplayLink,它与显示器的刷新率同步(我认为您将其传递给[UIScreen mainScreen]
)并且设计为动画使用,因此它应该会更好一些。 iOS 3.1+,但我怀疑支持3.0没什么意义。