2

そしてアドバイスありがとうございます!

私は fetchAllSubscriptionsWithCompletionHandler を使用していますが、プッシュ通知が送信された後、各 CKSubscription からのサブスクリプション ID が表示されます。サブスクリプション ID から CKRecord を取得するにはどうすればよいですか?

作成された CKReference からのリモート プッシュ通知が表示されません。CloudKit DashBoard を介して CKRecord とその関連レコードを確認できます。親レコードが作成されたときからプッシュ通知を受け取りますが、子レコードで CKReference が作成されたときは受け取りません。

-(void)SubscribeForReference:(CKRecord *)record
{

NSUserDefaults *trackSubscription = [NSUserDefaults standardUserDefaults];
BOOL hasSubscribed = [[NSUserDefaults standardUserDefaults] objectForKey:@"alreadySubscribedForReference"] != nil;

 //BOOL hasSubscribed = [trackSubscription  objectForKey:@"alreadySubscribedForReference"];

if (hasSubscribed == false) {
    //creates a subscription based on a CKReference between two ckrecords

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"sentences == %@", record.recordID];
    // 1) subscribe to record creations
    CKSubscription *subscriptionRelation =
    [[CKSubscription alloc] initWithRecordType:@"RecordTypeName"
                                     predicate:predicate
                                       options:CKSubscriptionOptionsFiresOnRecordCreation | CKSubscriptionOptionsFiresOnRecordUpdate | CKSubscriptionOptionsFiresOnRecordDeletion | CKSubscriptionOptionsFiresOnRecordUpdate];

    //http://stackoverflow.com/questions/27371588/cloudkit-notifications

    CKNotificationInfo *notificationInfo = [[CKNotificationInfo alloc] init];
    // I added this because of apple's documentation 
    notificationInfo.desiredKeys = @[@"word",@"identifier"];
    notificationInfo.alertLocalizationArgs = @[@"word"];  
    notificationInfo.alertLocalizationKey = @"%1$@";
    notificationInfo.shouldBadge = YES;

    subscriptionRelation.notificationInfo = notificationInfo;
    [self.privateDatabase saveSubscription:subscriptionRelation completionHandler:^(CKSubscription * _Nullable subscription, NSError * _Nullable error) {
        if (error == nil) {
            [trackSubscription setObject:subscription.subscriptionID forKey:@"alreadySubscribedForReference"];
            [trackSubscription synchronize];
        }else
            NSLog(@"something went wrong with saving the CKSubcription with error...\n%@\n",[error localizedDescription]);
    }];

}
else{
           NSLog(@"\nSubscribeForReference: ALREADY has subscription: %@   set for key 'alreadySubscribedForReference' \n\n ", [trackSubscription objectForKey:@"alreadySubscribedForReference"]);

}

}

以下のコードは、インターネット接続があれば、アプリの起動時に実行されます。

     -(void)runWhenAppStarts
      {
        CKFetchSubscriptionsOperation *fetchSubscriptionsOperation =   [CKFetchSubscriptionsOperation fetchAllSubscriptionsOperation];
        fetchSubscriptionsOperation.fetchSubscriptionCompletionBlock = ^(NSDictionary *subscriptionsBySubscriptionID, NSError *operationError) {
        if (operationError != nil)
        {     
        // error in fetching our subscription
        CloudKitErrorLog(__LINE__, NSStringFromSelector(_cmd), operationError);

        if (operationError.code == CKErrorNotAuthenticated)
        {
            // try again after 3 seconds if we don't have a retry hint
            //
            NSNumber *retryAfter = operationError.userInfo[CKErrorRetryAfterKey] ? : @3;
            NSLog(@"Error: %@. Recoverable, retry after %@ seconds", [operationError description], retryAfter);
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(retryAfter.intValue * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self subscribe];
            });
        }
    }
    else
    {
        if (self.subscribed == NO)
        {
            // our user defaults says we haven't subscribed yet
            //
            if (subscriptionsBySubscriptionID != nil && subscriptionsBySubscriptionID.count > 0)
            {
                // we already have our one CKSubscription registered with the server that we didn't know about
                // (not kept track in our NSUserDefaults) from a past app install perhaps,
                //
                NSLog(@"\nsubscriptionsBySubscriptionID (dictionary) = %@\n",subscriptionsBySubscriptionID);
                NSArray *allSubscriptionIDKeys = [subscriptionsBySubscriptionID allKeys];
                NSLog(@"\nallSubscriptionIDKeys (array) = %@\n",allSubscriptionIDKeys);

                if (allSubscriptionIDKeys != nil)
                {
                    [self updateUserDefaults:allSubscriptionIDKeys[0]];
                    for (NSString *subscriptions in allSubscriptionIDKeys) {
                        NSLog(@"subscriptionID: %@\n",subscriptions);
                    }
                }
            }
            else
            {
                // no subscriptions found on the server, so subscribe
                NSLog(@"...starting subscriptions on server...\n");
                [self startSubscriptions];
            }
        }
        else
        {
            // our user defaults says we have already subscribed, so check if the subscription ID matches ours
            //
            NSLog(@"...our user defaults says we have already subscribed, with subscriptionsBySubscriptionID = %@\nso check if the subscription ID matches the one already stored in NSUserDefaults...\n",subscriptionsBySubscriptionID);

            if (subscriptionsBySubscriptionID != nil && subscriptionsBySubscriptionID.count > 0)
            {
                // we already have our one CKSubscription registered with the server that
                // we didn't know about (not kept track in our NSUserDefaults) from a past app install perhaps,
                //
                //NSDictionary *subscriptionsBySubscriptionID has a structure of @{key: value} == @{NSString: CKSubscription}

                NSArray *allSubscriptionIDKeys = [subscriptionsBySubscriptionID allKeys];//contains the NSString representation of the subscriptionID.
                NSArray *allSubscriptionIDVALUES = [subscriptionsBySubscriptionID allValues];// the values are the corresponding CKSubscription objects

                for (CKSubscription *values in allSubscriptionIDVALUES) {
                    NSLog(@"\nCKSubscriptionValue = %@\n",values);

                }

                NSLog(@"\n...we already have our one CKSubscription registered with the server that..so lets look at allSubscriptionIDKeys =%@.\n\nvalues ...\nallSubscriptionIDVALUES = %@\n\n",allSubscriptionIDKeys,allSubscriptionIDVALUES);

                if (allSubscriptionIDKeys != nil)
                {
                    NSString *ourSubscriptionID = [[NSUserDefaults standardUserDefaults] objectForKey:kSubscriptionIDKey];
                    if (![allSubscriptionIDKeys[0] isEqualToString:ourSubscriptionID])
                    {
                        // our subscription ID doesn't match what is on the server, to update our to match
                        NSLog(@"...our subscription ID doesn't match what is on the server, going to update our  NSUserDefaults...\n");

                        [self updateUserDefaults:allSubscriptionIDKeys[0]];
                    }
                    else
                    {
                        // they match, no more work here
                        NSLog(@"...iCloud server already has this subscriptionID, so do nothing.i.e. don't subscribe again..\n");
                    }
                }
            }
        }
    }
};
[self.privateDatabase addOperation:fetchSubscriptionsOperation];
}
4

2 に答える 2