多次调用EKEventStoreChangedNotification

问题描述 投票:8回答:2

我在我的应用程序中使用EKEventStore。我抓住默认商店并注册EKEventStoreChangedNotification,以便在对日历进行更改时收到通知。但是,当进行更改时,通知的发件人会被调用几次(5-10)次,有时在每次调用之间最多会有15秒。这会弄乱我的代码并使事情变得更加困难。我能做些什么吗?

谢谢

iOS7编辑:似乎就像iOS7的发布一样,这个问题已经消失了。现在,无论对CalendarStore所做的更改,只发送一个EKEventStoreChangedNotification

iphone objective-c ios cocoa-touch ekeventkit
2个回答
17
投票

这是调度通知的确切方式以及每个实际通知的结果。根据我的经验,您可以期望收到至少一个项目更改通知(事件,提醒等),并至少再收到一个更改,以便对该项目的包含日历进行更改。

如果没有看到您的代码并知道正在做出哪些更改,我就无法对答案过于具体;但是,一般来说,您有两种选择。

  1. 更密切地观察更改 - 如果涉及与您的应用无关的事件,或者您已经处理了特定项目的更改,则可以安全地忽略某些通知。
  2. 将多个更改合并为一批处理程序代码。基本上,当您收到通知时,不要立即启动响应,而是启动一个计时器,该计时器将在一两秒内运行响应。然后,如果在计时器触发之前有另一个通知,您可以取消计时器并重置它。这样,您可以批量处理在短时间窗口内发出的多个通知,并且只响应一次(当计时器最终触发时)。

后一个解决方案是我的首选答案,可能看起来像(暂时忽略线程问题):

@property (strong) NSTimer *handlerTimer;

- (void)handleNotification:(NSNotification *)note {
    // This is the function that gets called on EKEventStoreChangedNotifications
    [self.handlerTimer invalidate];
    self.handlerTimer = [NSTimer timerWithTimeInterval:2.0
                                                target:self
                                              selector:@selector(respond)
                                              userInfo:nil
                                               repeats:NO];
    [[NSRunLoop mainRunLoop] addTimer:self.handlerTimer
                              forMode:NSDefaultRunLoopMode];
}

- (void)respond {
    [self.handlerTimer invalidate];
    NSLog(@"Here's where you actually respond to the event changes");
}

0
投票

我也有这个问题。经过一些调试后,我意识到我正在引起额外的EKEventStoreChangedNotification调用(例如,通过创建或删除EKReminders)。当我做EKEventStoreChangedNotification时,estore.commit()最终会被触发。

我通过声明全局变量来解决这个问题:

// the estore.commit in another function causes a new EKEventStoreChangedNotification. In such cases I will set the ignoreEKEventStoreChangedNotification to true so that I DON'T trigger AGAIN some of the other actions.
var ignoreEKEventStoreChangedNotification = false 

然后在AppDelegate.swift这样做,我听EKEventStoreChangedNotification

nc.addObserver(forName: NSNotification.Name(rawValue: "EKEventStoreChangedNotification"), object: estore, queue: updateQueue) {
            notification in

        if ignoreEKEventStoreChangedNotification {
            ignoreEKEventStoreChangedNotification = false
            return
        }

        // Rest of your code here.

}

在我更改estore的函数中,我这样做:

//
// lots of changes to estore here...
//
ignoreEKEventStoreChangedNotification = true        // the estore.commit causes a new EKEventStoreChangedNotification because I made changes. Ignore this EKEventStoreChangedNotification - I know that changes happened, I caused them!
try estore.commit()

它与全局变量不同(特别是如果你正在进行函数式编程),但它有效。

© www.soinside.com 2019 - 2024. All rights reserved.