我会推荐使用NSOperation和NSOperationQueue来管理你需要能够任意取消的后台活动。
NSOperation的取消和NSOperationQueue的取消所有操作是要看的方法。
为了让消息从后台回到主线程,dispatch_async-to-main-thread-queue技术很好。您可以将此与NSOperation的委托协议结合起来,将您想要发回的邮件进行编码。
E.g.
@protocol MyOperationDelegate
- (void) operationStarted:(MyOperation *)operation;
- (void) makingProgressOnItem:(id)anItem otherInterestingItem:(NSDictionary *)otherItem remainingCount:(NSUInteger)count;
- (void) operationWillFinish:(MyOperation *)operation;
@end
@interface MyOperation
id <MyOperationDelegate> delegate;
@end
@implementation MyOperation
...
- (void) cancel
{
[super cancel];
// Tell the delegate we're about to finish (due to cancellation).
dispatch_sync (dispatch_get_main_queue(), ^{
[self.delegate operationWillFinish:self];
});
}
- (void) main
{
// Check for cancellation
if (self.isCancelled) return;
// Starting
dispatch_sync (dispatch_get_main_queue(), ^{
[self.delegate operationStarted:self];
});
if (self.isCancelled) return; // Another cancel check
// Send async progress messages periodically while doing some work
while (workNotDone)
{
// Do some work ...
dispatch_async (dispatch_get_main_queue(), ^{
[self.delegate makingProgressOnItem:foo otherInterestingItem:bar remainingCount:baz];
});
if (self.isCancelled) return;
}
// About to finish
if (!self.isCancelled) {
dispatch_sync (dispatch_get_main_queue(), ^{
[self.delegate operationWillFinish:self];
});
}
}
@end
KVO是没有良好的间通信;在发生关键值更改的线程上收到观察结果。所以,如果你的后台线程改变了一个值,你的后台线程将会收到关于它的KVO。可能不是你想要的。
爷爷的-performSelectorOnMainThread:withObject:waitUntilDone:继续是让消息回到主线程的好方法。限制是你的消息只能访问一个基于对象的参数。 dispatch_async到主线程没有这个限制。
如果您想从后台线程向主线程发出异步(或同步)NSNotification,则需要使用-performSelectorOnMainThread。
NSNotification *note = [NSNotification notificationWithName:FinishedABunchOfWorkNotification object:self userInfo:nil];
[[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:note waitUntilDone:YES];
GCD非常适合这类工作。每当用户键入内容时,我都会有一个计时器。所以当它触发时(用户在2秒钟内没有按下按键),它会调用dispatch_async来触发处理,并在完成后向主线程发送NSNotification。 – 2011-01-19 23:38:10
你确定观察者在主线程中得到通知吗?我没有在iOS上测试过,但是在Mac OS X上测试了IIRC,观察发生在任何引起变化的线程上。 – 2011-01-20 15:49:02
我一直没有清楚 - 你可以在你用performSelectorOnMainThread调用的方法中做你的UI的东西,或者你可以通过主线程上的该方法通过KVO来触发它。我认为你是正确的关于变化的线程上发生的通知。 – 2011-01-20 18:21:57