2009-12-29 43 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

相關問題