多次调用EKEventStoreChangedNotification

时间:2012-08-30 21:04:01

标签: iphone objective-c ios cocoa-touch ekeventkit

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

由于

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

2 个答案:

答案 0 :(得分:17)

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

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

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

    @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");
    }
    

答案 1 :(得分:0)

我也遇到了这个问题。经过一些调试后,我意识到我正在引起额外的EKEventStoreChangedNotification调用(例如,通过创建或删除EKReminder)。我进行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.

}

在我对电子商店进行更改的函数中,我这样做:

//
// 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()

使用全局变量(特别是如果您要进行函数编程)不是很好,但是它可以工作。