谢谢你的建议!
我正在使用 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"]);
}
}
下面的代码在应用程序启动时运行,前提是有 Internet 连接:
-(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];
}