CK订阅不起作用

Posted

技术标签:

【中文标题】CK订阅不起作用【英文标题】:CKSubscription not working 【发布时间】:2015-06-18 21:26:27 【问题描述】:

我正在我的 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时,它返回null,之后每次打开应用程序时,它都能正确获取它们。但是,当在一台设备(例如 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 永远不会触发。

【问题讨论】:

您可能需要查看您的开发人员配置文件配置。最常见的错误与使用错误配置文件的 sanbox 环境有关... 你到底是什么意思?我应该具体检查我的配置什么?你说的很有道理。 【参考方案1】:

你有一个空的 alertbody

notificationInfo1.alertBody = @"";

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

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 中收到通知。

【讨论】:

好的,我认为我们在 CKFetchNotificationChangesOperation 上走在了正确的轨道上。您能否通过一个示例来更新您的答案,说明如何在选择我的菜单时将其与我的代码设置一起使用。

以上是关于CK订阅不起作用的主要内容,如果未能解决你的问题,请参考以下文章

CloudKit 订阅不起作用

为啥我的 Absinthe GraphQL 订阅不起作用?

CloudKit 推送通知订阅不起作用

没有 ngOnDestroy,角度取消订阅不起作用

为啥 Azure 事件中心订阅者不起作用?

订阅不起作用,订阅字段类中的代码不运行