2009-12-29 41 views
18

我有一个NSOperation。完成后,我启动NSNotificationCenter,让程序知道NS操作已完成并更新gui。主线程上的NSOperation和NSNotificationCenter

据我了解,NSNotification的监听器不会在主线程上运行,因为NSOperation不在主线程中。

我该如何让侦听器在我的事件发生时在主线程上运行?

[[NSNotificationCenter defaultCenter] postNotificationName:@"myEventName" object:self]; 

回答

22

您可以使用performSelectorOnMainThread:withObject:waitUntilDone:并使用助手方法,其方法与以下示例类似。

..... 
[self performSelectorOnMainThread:@selector(fireNotification) withObject:nil waitUntilDone:YES]; 
... 

- (void)fireNotification { 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"myEventName" object:self]; 
} 

如果不等到正在做,你需要考虑在其他线程可以是指可以在主线程被调用之前已清理对象的情况。

6

如果您使用的是10.6,则还可以使用setCompletionBlock:。 它这样使用:

NSOperation*op= .... ; 
[op setCompletionBlock:^{ 
    dispatch_async(dispatch_get_main_queue(),^{ 
     code to be run on the main thread after the operation is finished. 
    }); 
}]; 

有关块和GCD,this article一般介绍是非常有帮助的。我发现GCD & setCompletionBlock比NSNotification更容易阅读。一个警告是,它只能在10.6上运行!

+1

如果使用“iPhone”标签,提问者可能不是10.6。 – 2009-12-29 16:01:54

+0

你是对的,亚历克斯。愚蠢的我。 – Yuji 2009-12-29 17:33:31

+0

感谢您的提示。 – 2011-11-23 13:30:15

40

更新: 调度队列使在主线程上发布通知非常容易。

dispatch_async(dispatch_get_main_queue(),^{ 
    [[NSNotificationCenter defaultCenter] postNotification...]; 
}); 

要等待通知处理程序完成,只需将dispatch_async替换为dispatch_sync即可。


继notnoop的答案,这里的一些基础设施,您可以使用主线程安全上发表您的通知,而无需等待他们完成。希望有人会觉得这有帮助!

NSNotificationCenter + Utils.h:

@interface NSNotificationCenter (Utils) 

-(void)postNotificationOnMainThread:(NSNotification *)notification; 
-(void)postNotificationNameOnMainThread:(NSString *)aName object:(id)anObject; 
-(void)postNotificationNameOnMainThread:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo; 

@end 

NSNotificationCenter + Utils.m:

@interface NSNotificationCenter (Utils_Impl) { 
} 

-(void)postNotificationOnMainThreadImpl:(NSNotification*)notification; 
-(void)postNotificationNameOnMainThreadImpl:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo; 

@end 

@implementation NSNotificationCenter (Utils) 

-(void)postNotificationOnMainThread:(NSNotification *)notification { 
    [notification retain]; 
    [notification.object retain]; 
    [self performSelectorOnMainThread:@selector(postNotificationOnMainThreadImpl:) 
          withObject:notification 
         waitUntilDone:NO]; 
} 

-(void)postNotificationNameOnMainThread:(NSString *)aName object:(id)anObject { 
    [self postNotificationNameOnMainThread:aName object:anObject userInfo:nil]; 
} 

-(void)postNotificationNameOnMainThread:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo { 
    [aName retain]; 
    [anObject retain]; 
    [aUserInfo retain]; 

    SEL sel = @selector(postNotificationNameOnMainThreadImpl:object:userInfo:); 
    NSMethodSignature* sig = [self methodSignatureForSelector:sel]; 
    NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:sig]; 
    [invocation setTarget:self]; 
    [invocation setSelector:sel]; 
    [invocation setArgument:&aName atIndex:2]; 
    [invocation setArgument:&anObject atIndex:3]; 
    [invocation setArgument:&aUserInfo atIndex:4]; 
    [invocation invokeOnMainThreadWaitUntilDone:NO]; 
} 

@end 

@implementation NSNotificationCenter (Utils_Impl) 

-(void)postNotificationOnMainThreadImpl:(NSNotification*)notification { 
    [self postNotification:notification]; 
    [notification.object release]; 
    [notification release]; 
} 

-(void)postNotificationNameOnMainThreadImpl:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo { 
    [self postNotificationName:aName object:anObject userInfo:aUserInfo]; 
    [aName release]; 
    [anObject release]; 
    [aUserInfo release]; 
} 

@end 

NSInvocation的+ Utils.h:

@interface NSInvocation (Utils) 

-(void)invokeOnMainThreadWaitUntilDone:(BOOL)wait; 

@end 

NSInvocation的+ Utils.m:

@implementation NSInvocation (Utils) 

-(void)invokeOnMainThreadWaitUntilDone:(BOOL)wait 
{ 
    [self performSelectorOnMainThread:@selector(invoke) 
          withObject:nil 
         waitUntilDone:wait]; 
} 

@end 
+1

非常好。感谢您花时间编写此代码。 – 2012-02-16 19:32:30

5

要在这里扩大Danra的回答是该类别的ARC兼容的版本我放在一起:

NSNotificationCenter + Threads.h

@interface NSNotificationCenter (Threads) 

-(void)postNotificationOnMainThread:(NSNotification *)notification; 
-(void)postNotificationNameOnMainThread:(NSString *)name object:(id)object; 
-(void)postNotificationNameOnMainThread:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo; 

@end 

NSNotificationCenter +主题。m

@implementation NSNotificationCenter (Threads) 

-(void)postNotificationOnMainThread:(NSNotification *)notification 
{ 
    [self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO]; 
} 

-(void)postNotificationNameOnMainThread:(NSString *)name object:(id)object 
{ 
    [self postNotificationNameOnMainThread:name object:object userInfo:nil]; 
} 

-(void)postNotificationNameOnMainThread:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self postNotificationName:name object:object userInfo:userInfo]; 
    }); 
} 

@end 
+0

对我很好。谢谢你,奥利弗! – Elliot 2014-09-03 18:54:34

相关问题