2017-07-11 2 views
1

et merci pour vos conseils! J'utilise fetchAllSubscriptionsWithCompletionHandler et je vois l'identificateur subscritionID de chaque CKSubscription après l'envoi de la notification push. Comment puis-je récupérer le CKRecord à partir de l'abonnementID?Comment récupérer le CKRecord à partir du CKSubscriptionID provenant de fetchAllSubscriptionsWithCompletionHandler?

Je ne vois pas la notification Push à distance à partir d'un CKReference créé. Je peux voir le CKRecord et son enregistrement lié via CloudKit DashBoard. Je reçois une notification Push à partir de la création de son enregistrement parent, mais pas lors de la création de CKReference sur l'enregistrement enfant.

-(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 = @"%[email protected]"; 
    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"]); 

} 

} 

Le code ci-dessous est couru lorsque l'application est lancée, à la condition est une connexion 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]; 
} 

Répondre

0

Lorsque vous allez chercher les abonnements, vous ne recevez pas un code d'enregistrement spécifique. Au lieu de cela, l'abonnement .recordType vous dira le de type d'enregistrer ces moniteurs d'abonnement. Généralement, si vous avez 1 000 utilisateurs, vous aurez 1 000 instances de l'enregistrement et chaque utilisateur créera des sous-marins à surveiller lorsque leur instance sera modifiée.

Lorsque l'abonnement est déclenché, vous recevrez une notification. Vous pouvez utiliser CKFetchNotificationChangesOperation pour récupérer les notifications. Chaque notif inclut une valeur .recordID qui vous indique précisément quel enregistrement a été modifié et a déclenché l'abonnement.

Vous interrogez actuellement les sous-marins pour vous assurer que l'utilisateur s'est correctement abonné. Ensuite, vous devez également interroger les notifications avec CKFetchNotificationChangesOperation pour voir quels enregistrements ont été mis à jour lorsque les abonnements ont été déclenchés.

+0

Merci pour votre réponse! CKFetchSubscriptionsOperation * fetchSubscriptionsOperation provient de l'exemple de code CloudPhoto d'Apple. Il récupère les ID cksubscription non lus qui sont stockés sur iCloud. Mon problème est maintenant que j'ai ces subscriptionID, comment puis-je obtenir le CKRecord qui a causé la notification push? Par exemple, j'ai ajouté 5 enregistrements à iCloud, mais j'ai seulement vu une notification 1-push. Comment récupérer le CKRecord des autres 4-CKRecords qui ont provoqué la notification push? –

+0

Ci-dessous ce que je peux voir après avoir récupéré les abonnements qui sont sur iCloud ...... nous avons déjà notre un CKSubscription enregistré avec le serveur que ... permet de regarder allSubscriptionIDKeys = ( "AB3A1141-B86C-445E-8B4C -06142F2717C9" , "98D91BCB-4D01-429F-90FB-D26C91993348", "54FF397E-373D-4289-B6C0-D553BF104CD1", "A07AC98F-AFCF-48D6-8DA1-A4F986B6E246", « 3E283535-8BAA-4BD2 -8C8C-5E83F5274632" "F35ADFBE-FEEA-4531-9BF3-D76F70F4E87A" "CFD160D3-EB99-4933-965A-2EF5C1C68798" "F1C7DA0C-7DBA-4D4C-BB0A-34AD180FD410" ). –

+0

dictionnaire valeurs tirées par les cheveux de CKSubscription ... allSubscriptionIDVALUES = ( « , subscriptionOptions = 7, subscriptionID = AB3A1141-B86C-445E-8B4C-06142F2717C9, zoneID = (nul)> " –