CKFetchNotificationChangesOperation返回旧通知

时间:2014-10-29 13:12:49

标签: ios objective-c notifications icloud cloudkit

我正在开发基于CloudKit的应用程序,该应用程序使用CKSubscription通知来跟踪公共数据库的更改。每当应用程序收到推送通知时,我都会使用CKFetchNotificationChangesOperation检查通知队列,并在处理完每个通知后将其标记为:

    __block NSMutableArray *notificationIds = [NSMutableArray new];

CKFetchNotificationChangesOperation *operation = [[CKFetchNotificationChangesOperation alloc] initWithPreviousServerChangeToken:self.serverChangeToken];
operation.notificationChangedBlock = ^(CKNotification *notification) {
    [notificationIds addObject:notification.notificationID];
    [self processRemoteNotification:notification withCompletionHandler:completionHandler];
};

__weak CKFetchNotificationChangesOperation *operationLocal = operation;
operation.fetchNotificationChangesCompletionBlock = ^(CKServerChangeToken *serverChangeToken, NSError *operationError) {
    if (operationError) {
        NSLog(@"Unable to fetch queued notifications: %@", operationError);
    }
    else {
        self.serverChangeToken = serverChangeToken;
        completionHandler(UIBackgroundFetchResultNewData);

        // Mark the processed notifications as read so they're not delivered again if the token gets reset.
        CKMarkNotificationsReadOperation *markReadOperation = [[CKMarkNotificationsReadOperation alloc] initWithNotificationIDsToMarkRead:[notificationIds copy]];
        [notificationIds removeAllObjects];

        markReadOperation.markNotificationsReadCompletionBlock = ^(NSArray *notificationIDsMarkedRead, NSError *operationError) {
            if (operationError) {
                NSLog(@"Unable to mark notifications read: %@", operationError);
            }
            else {
                NSLog(@"%lu notifications marked read.", (unsigned long)[notificationIDsMarkedRead count]);
            }
        };

        [[CKContainer defaultContainer] addOperation:markReadOperation];

        if (operationLocal.moreComing) {
            NSLog(@"Fetching more");
            [self checkNotificationQueueWithCompletionHandler:completionHandler];
        }
    }
};

[[CKContainer defaultContainer] addOperation:operation];

据我了解,标记通知读取将使其在将来的队列提取中不会显示,即使服务器更改标记重置为nil也是如此。相反,当每个fetch只有1或2个新的时,我会在每次获取中获得很多旧的通知。我可以从notificationType标志中检测到旧的,但我担心它们会出现。我在某处错过了一步吗?

2 个答案:

答案 0 :(得分:3)

我知道这有点旧,但我遇到了同样的问题。我想我想出来了(至少在我的情况下)。

在我的代码中,我做的和你一样:也就是说,将所有的notificationID添加到数组中并在我的CKMarkNotificationsReadOperation中使用它,并且每次都返回所有通知(尽管如你所说,一种“ReadNotification”)。

我更改了我的代码,以便我只向我的数组添加“新”通知,而不是“ReadNotification”项,并发送它们。修好了。

似乎将通知发送回服务器以标记为已读,即使它已被标记为已读,也会导致它再次作为“ReadNotification”返回。

我希望这有助于某人。

答案 1 :(得分:0)

文档不是很清楚它应该说:“将通知标记为已读取会阻止后续提取操作返回”... 作为查询通知类型。进一步澄清它应该说通知将作为读取类型返回。

如果根本没有返回,那么错过推送的其他设备就不会知道有什么变化了!