CKПодписка не работает

Я создаю свои два CKSubscriptions в методе didFinishLaunchingWithOptions моего делегата приложения как таковом.

- (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, он возвращает ноль, и каждый раз, когда я открываю приложение после этого, оно может правильно их получить. Однако, когда запись создается или удаляется на одном устройстве, скажем, на 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, к сожалению, никогда не срабатывает.


person Community    schedule 18.06.2015    source источник
comment
Возможно, вы захотите просмотреть конфигурацию своего профиля обеспечения разработчика. Самая распространенная ошибка связана с окружением sanbox с неправильными профилями...   -  person nstefan    schedule 22.06.2015
comment
Что именно ты имеешь ввиду? Что конкретно я должен проверить для своей конфигурации? То, что вы говорите, действительно имеет смысл.   -  person    schedule 23.06.2015


Ответы (1)


У вас есть пустое тело оповещения

уведомлениеInfo1.alertBody = @"";

При этом вы не будете получать push-уведомления, когда ваше приложение неактивно. Когда вы вручную активируете свое приложение, вы сможете запрашивать уведомления с помощью 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.

person Edwin Vermeer    schedule 22.06.2015
comment
Хорошо, я думаю, что мы на правильном пути с CKFetchNotificationChangesOperation. Не могли бы вы обновить свой ответ примером того, как использовать это с моей настройкой кода, когда выбрано мое меню. - person ; 23.06.2015