接收两个或多个通知时,仅执行一次选择器

时间:2015-11-14 17:33:19

标签: ios objective-c cocoa-touch nsnotificationcenter nsnotification

我正在尝试在发生某些事件时执行选择器,例如:

  1. 该应用已激活
  2. 互联网可访问性状态从无法访问变为可访问
  3. 我在使用以下代码发生这些事件时发布通知

    [[NSNotificationCenter defaultCenter] postNotificationName:Notif_Name object:nil];
    

    我希望在同一个UIViewController实例中收到通知时执行选择器,因此我将其注册为viewDidLoad

    中的观察者
    [[NSNotificationCenter defaultCenter] addObserverForName:Notif_Name object:nil queue:nil usingBlock:^(NSNotification *note) {
    
        [self performSelectorOnMainThread:@selector(selectorName) withObject:nil waitUntilDone:NO];
    }];
    

    现在,我观察到的这些事件可能同时发生。如何确保我的选择器只执行一次?

3 个答案:

答案 0 :(得分:1)

Cocoa Touch中的NSNotificationQueue支持合并通知。

不使用通知 center 直接发布通知,而是将通知排入队列并告知队列组合相似或相同的通知。您可以根据通知名称和发件人之一或两者匹配它。您没有为通知提供对象,因此您只能使用名称合并。

NSNotification * note = [NSNotification notificationWithName:Notif_Name object:nil]

[[NSNotificationQueue defaultQueue] enqueueNotification:note
                                           postingStyle:NSPostASAP
                                           coalesceMask:NSNotificationCoalescingOnName
                                               forModes:nil];

答案 1 :(得分:0)

您可以保留一个标志,告诉您是否已执行了selectorName并保护它免受多线程访问。

@interface ViewController ()
@property (nonatomic) BOOL executed;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(executeSelector) name:Notif_Name object:nil];
}

- (void)executeSelector {
    @synchronized (self) {
        if (!self.executed) {
            self.executed = YES;
            [[NSNotificationCenter defaultCenter] removeObserver:self];
            [self performSelectorOnMainThread:@selector(selectorName) withObject:nil waitUntilDone:NO];
        }
    }
}

@end

答案 2 :(得分:0)

你也可以尝试以下方法:

[[NSNotificationCenter defaultCenter] addObserverForName:Notif_Name object:nil queue:nil usingBlock:^(NSNotification *note) {
  [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(selectorName) object:nil];
  [self performSelector:@selector(selectorName) withObject:nil afterDelay:1.0];
}];

等待一秒钟,直到您执行操作并取消所有待处理的请求...