CK订阅不工作

CKSubscription not working

我正在我的 App Delegate 的 didFinishLaunchingWithOptions 方法中创建我的两个 CKSubscriptions

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
    [[UIApplication sharedApplication] registerForRemoteNotifications];

    _myContainer = [CKContainer containerWithIdentifier:@"iCloud.com.isaranjha.Copyfeed"];
    _privateDatabase = [_myContainer privateCloudDatabase];

    [_privateDatabase fetchSubscriptionWithID:@"subscription" completionHandler:^(CKSubscription *subscription, NSError *error){

        if (subscription) {

        } else {

            NSPredicate *predicate = [NSPredicate predicateWithValue:YES];
            CKSubscription *subscription = [[CKSubscription alloc] initWithRecordType:@"Strings" predicate:predicate subscriptionID:@"subscription" options:CKSubscriptionOptionsFiresOnRecordCreation | CKSubscriptionOptionsFiresOnRecordDeletion | CKSubscriptionOptionsFiresOnRecordUpdate];
            CKNotificationInfo *notificationInfo = [CKNotificationInfo new];
            notificationInfo.alertBody = @"";
            notificationInfo.shouldSendContentAvailable = YES;
            subscription.notificationInfo = notificationInfo;

            [_privateDatabase saveSubscription:subscription completionHandler:^(CKSubscription *subscription, NSError *error) {

            }];

        }

    }];


    [_privateDatabase fetchSubscriptionWithID:@"subscription1" completionHandler:^(CKSubscription *subscription, NSError *error){

        if (subscription) {

        } else {

            NSPredicate *predicate1 = [NSPredicate predicateWithValue:YES];
            CKSubscription *subscription1 = [[CKSubscription alloc] initWithRecordType:@"Images" predicate:predicate1 subscriptionID:@"subscription1" options:CKSubscriptionOptionsFiresOnRecordCreation | CKSubscriptionOptionsFiresOnRecordDeletion | CKSubscriptionOptionsFiresOnRecordUpdate];
            CKNotificationInfo *notificationInfo1 = [CKNotificationInfo new];
            notificationInfo1.shouldSendContentAvailable = YES;
            notificationInfo1.alertBody = @"";
            subscription1.notificationInfo = notificationInfo1;
            [_privateDatabase saveSubscription:subscription1 completionHandler:^(CKSubscription *subscription, NSError *error) {

            }];

        }

    }];

    ViewController *view = [[ViewController alloc] init];

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:view];
    self.window.rootViewController = navController;

    return YES;
}

创建成功,当我退出 NSError 时,它 returns 为空,此后每次我打开应用程序时,它都能正确获取它们。但是,当在一台设备上创建或删除记录时,比如 iPhone,通知不会在另一台设备上触发(或者没有被正确接收),比如 Mac。这就是我在 Mac.

上收听通知的方式
- (void)application:(NSApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    NSLog(@"CKSubscription received.");

    CKQueryNotification *cloudKitNotification = [CKQueryNotification notificationFromRemoteNotificationDictionary:userInfo];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"CloudKitUpdated" object:nil userInfo:@{@"ckNotification" : cloudKitNotification}];
}

不幸的是 NSLog 从未触发。

你有一个空的 alertbody

notificationInfo1.alertBody = @"";

有了它,当您的应用程序处于非活动状态时,您将不会收到推送通知。当您手动激活您的应用程序时,您将能够使用 CKFetchNotificationChangesOperation 查询通知。这是我在 EVCloudKitDao:

中如何使用它的片段
public func fetchChangeNotifications(skipRecordID: CKRecordID?, inserted:(recordID:String, item: EVCloudKitDataObject) -> Void, updated:(recordID: String, item: EVCloudKitDataObject) -> Void, deleted:(recordId: String) -> Void, completed:()-> Void) {
    var defaults = NSUserDefaults.standardUserDefaults()
    var array: [NSObject] = [NSObject]()
    var operation = CKFetchNotificationChangesOperation(previousServerChangeToken: self.previousChangeToken)
    operation.notificationChangedBlock = { notification in
        if notification.notificationType == .Query  {
            if var queryNotification = notification as? CKQueryNotification {
                array.append(notification.notificationID)
                if skipRecordID != nil && skipRecordID?.recordName != queryNotification.recordID.recordName {
                    if queryNotification.queryNotificationReason == .RecordDeleted {
                        deleted(recordId: queryNotification.recordID.recordName)
                    } else {
                        EVCloudKitDao.publicDB.getItem(queryNotification.recordID.recordName, completionHandler: { item in
                            EVLog("getItem: recordType = \(EVReflection.swiftStringFromClass(item)), with the keys and values:")
                            EVReflection.logObject(item)
                            if queryNotification.queryNotificationReason == .RecordCreated {
                                inserted(recordID: queryNotification.recordID.recordName, item: item)
                            } else if queryNotification.queryNotificationReason == .RecordUpdated {
                                updated(recordID: queryNotification.recordID.recordName, item: item)
                            }
                        }, errorHandler: { error in
                            EVLog("ERROR: getItem for change notification.\n\(error.description)")
                        })
                    }
                }
            }
        }
    }
    operation.fetchNotificationChangesCompletionBlock = { changetoken, error in
        var op = CKMarkNotificationsReadOperation(notificationIDsToMarkRead: array)
        op.start()
        EVLog("changetoken = \(changetoken)")
        self.previousChangeToken = changetoken

        if operation.moreComing  {
            self.fetchChangeNotifications(skipRecordID, inserted: inserted, updated: updated, deleted: deleted, completed:completed)
        } else {
            completed()
        }
    }
    operation.start()
}

当您的应用程序处于活动状态时,您应该会在应用程序 didReceiveRemoteNotification 中收到通知。