1.) NSOperation 队列是一个合理的选择吗?如果没有,还有什么?
NSOperationQueue 听起来很合理。
当然,您可以选择:pthreads、libdispatch(又名 GCD)、建立在 pthreads 之上的 c++ 线程库等,等等。你喜欢的模特。
2.) 如何减少睡眠? (显然我希望工作获得尽可能多的周期/合理的,而且我不确定我的睡眠是否对所有要更新的 UI 做任何事情。)
不要睡觉 =) 您可以为您的 ui 元素使用计时器或显式回调或通知来通知依赖项。如果依赖项执行 ui 更新,那么您可能会将消息添加到主线程的消息队列中。
3.) 是否有更好的技术来使 UI 保持最新状态?例如,我可以使用 NSTimer 或其他方法向 UI 发送消息,告诉它更新和/或检查按钮的状态吗?
这真的取决于你在做什么。如果您只想更新进度条,则可以从辅助线程写入值并从主线程读取值。然后在主运行循环上使用计时器定期向您的对象发送消息以更新其显示(基于当前值)。对于诸如未分级的进度指示器之类的东西,这可能很好。
另一种选择对事件或阶段更有用:它将涉及随着进度的进行从辅助线程发布更新(例如通知或对委托的回调)(更多信息在 #2 下)。
更新
我不确定这在 iOS 模型中是否合适,但听起来确实如此。
是的,这很好 - 您可以采取许多方法。哪个是“最好的”取决于上下文。
我目前的理解是在一个线程中启动 UI(不是主线程!),
您确实没有明确启动 UI;主线程(通常)通过将事件和消息推送到主线程来驱动。主线程使用运行循环并在运行循环的每次迭代中处理排队的消息/事件。您还可以在将来安排这些消息(稍后会详细介绍)。话虽如此,您对 UIKit 和 AppKit(如果您以 osx 为目标)对象的所有消息都应该在主线程上(作为概括,您最终会了解到这有例外)。如果您有一个与消息传递 UIKit 对象的方法完全分离的特定实现,并且该程序是线程安全的,那么您实际上可以从任何线程执行这些消息,因为它不会影响 UIKit 实现的状态。最简单的例子:
@interface MONView : UIView
@end
@implementation MONView
// ...
- (NSString *)iconImageName { return @"tortoise.png"; } // pure and threadsafe
@end
启动我的工作线程,使用计时器向 UI 生成信号以查看进度值并适当地更新进度条。出于这个特定应用程序的目的,你的倒数第二段已经足够了,我不需要深入到最后一段的长度(至少现在是这样)。谢谢。
为此,您可以使用类似的方法:
@interface MONView : UIView
{
NSTimer * timer;
MONAsyncWorker * worker; // << this would be your NSOperation subclass, if you use NSOperation.
}
@end
@implementation MONView
// callback for the operation 'worker' when it completes or is cancelled.
- (void)workerWillExit
{
assert([NSThread isMainThread]); // call on main
// end recurring updates
[self.timer invalidate];
self.timer = nil;
// grab what we need from the worker
self.worker = nil;
// update ui
}
// timer callback
- (void)timerUpdateCallback
{
assert([NSThread isMainThread]); // call on main
assert(self.worker);
double progress = self.worker.progress;
[self updateProgressBar:progress];
}
// controller entry to initiate an operation
- (void)beginDownload:(NSURL *)url
{
assert([NSThread isMainThread]); // call on main
assert(nil == worker); // call only once in view's lifetime
// create worker
worker = [[MONAsyncWorker alloc] initWithURL:url];
[self.operationQueue addOperation:worker];
// configure timer
const NSTimeInterval displayUpdateFrequencyInSeconds = 0.200;
timer = [[NSTimer scheduledTimerWithTimeInterval:displayUpdateFrequencyInSeconds target:self selector:@selector(timerUpdateCallback) userInfo:nil repeats:YES] retain];
}
@end
请注意,这是一个非常原始的演示。将计时器、更新处理和操作放在视图的控制器而不是视图中也更常见。