8

アプリで EKEventStore を使用しています。デフォルトのストアを取得EKEventStoreChangedNotificationし、カレンダーに変更が加えられたときに通知されるように登録します。ただし、変更が行われると、通知の送信者が数回 (5 ~ 10 回) 呼び出され、各呼び出しの間に最大 15 秒かかる場合があります。これは私のコードを台無しにし、作業をより困難にします。これについて私にできることはありますか?

ありがとう

iOS7 編集: iOS7のリリース時点で、この問題は解消されたようです。これで、CalendarStore に加えられた変更に関係なく、1 つだけEKEventStoreChangedNotificationが送信されます。

4

2 に答える 2

17

これは、通知がどのようにディスパッチされ、それぞれが実際に何について通知しているかの正確な結果です。私の経験では、アイテム (イベント、リマインダーなど) への変更について少なくとも 1 つの通知を受け取り、そのアイテムを含むカレンダーへの結果としての変更について少なくとも 1 つの通知を受け取ることが期待できます。

あなたのコードを見て、どのような変更が加えられているかを知らなければ、答えについてあまり具体的に言うことはできません。ただし、一般に、2 つのオプションがあります。

  1. 変更をより詳しく観察します。アプリに関係のないイベントに関する通知や、特定のアイテムの変更を既に処理している場合は、通知を無視しても問題ありません。
  2. 複数の変更をハンドラー コードの 1 つのバッチにまとめます。基本的に、通知を受け取ったら、すぐに応答を開始するのではなく、1 秒か 2 秒で応答を実行するタイマーを開始します。その後、タイマーが起動する前に別の通知が届いた場合は、タイマーをキャンセルしてリセットできます。このようにして、短い時間枠内に来る複数の通知をまとめて、それらに 1 回だけ応答することができます (最終的にタイマーが起動したとき)。

後者の解決策は私の好みの答えであり、次のようになります (一時的にスレッドの問題を無視します)。

@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");
}
于 2012-08-30T21:22:20.100 に答える
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()

グローバル変数ではきれいではありませんが(特に関数型プログラミングに興味がある場合)、機能します。

于 2018-09-03T16:02:24.343 に答える