2017-07-11 1 views
1

und danke für Ihren Rat!Wie Abrufen des CKRecord von der CKSubscriptionID, die von FetchAllSubscriptionsWithCompletionHandler kam?

Ich benutze fetchAllSubscriptionsWithCompletionHandler, und ich sehe die SubscrictionID von jedem CKSubscription, nachdem die Push-Benachrichtigung gesendet wird. Wie kann ich den CKRecord von der SubscriptionID abrufen?

Ich sehe die Remote Push Notification nicht von einer CKReference, die erstellt wurde. Ich kann den CKRecord und den zugehörigen Datensatz über CloudKit DashBoard anzeigen. Ich erhalte eine Push-Benachrichtigung, wenn der übergeordnete Datensatz erstellt wird, aber nicht, wenn die CKReference für den untergeordneten Datensatz erstellt wird.

-(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"]); 

} 

} 

Der Code unten lief, wenn die App gestartet wird, sofern eine Internetverbindung:

 -(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]; 
} 

Antwort

0

Wenn Sie Abonnements holen, müssen Sie nicht einen bestimmten Datensatz-ID erhalten. Stattdessen teilt Ihnen das Abonnement .recordType den Typ des Datensatzes dieser Abonnementüberwachung mit. Wenn Sie 1.000 Benutzer haben, haben Sie normalerweise 1.000 Instanzen des Datensatzes, und jeder Benutzer würde Subs erstellen, die überwacht werden sollen, wenn ihre Instanz geändert wird.

Wenn das Abonnement ausgelöst wird, erhalten Sie eine Benachrichtigung. Sie können CKFetchNotificationChangesOperation verwenden, um die Benachrichtigungen abzurufen. Jede Benachrichtigung enthält einen .recordID Wert, der Ihnen speziell mitteilt, welcher Datensatz sich geändert hat und das Abonnement ausgelöst hat.

Sie fragen derzeit nach den Subs, um sicherzustellen, dass der Benutzer ordnungsgemäß abonniert wurde. Als Nächstes müssen Sie auch die Benachrichtigungen mit CKFetchNotificationChangesOperation abfragen, um zu sehen, welche Datensätze bei der Ausführung der Abonnements aktualisiert wurden.

+0

Vielen Dank für Ihre Antwort! Die CKFetchSubscriptionsOperation * fetchAbonnementsOperation stammt aus Apples CloudPhoto-Beispielcode. Er ruft die ungelesenen cksubsription-IDs ab, die in iCloud gespeichert sind. Mein Problem ist jetzt, dass ich diese subscriptionIDs habe, wie bekomme ich das CKRecord, das die Push-Benachrichtigung verursachte? Ich habe beispielsweise 5 Datensätze zu iCloud hinzugefügt, aber nur 1-Push-Benachrichtigungen angezeigt. Wie erhalte ich den CKRecord von den anderen 4-CKRecords, die die Push-Benachrichtigung verursacht haben? –

+0

Unten ist, was ich nach dem Abrufen der Abonnements, die auf iCloud sind, sehen kann ...... wir haben bereits unsere eine CKSubscription registriert mit dem Server, dass..alsallSubscriptionIDKeys = ( "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

Fetched CKSubscription Wörterbuch Werte ... allSubscriptionIDVALUES = ( „, subscriptionOptions = 7, subscriptionID = AB3A1141-B86C-445E-8B4C-06142F2717C9, zoneID = (null)> " –

Verwandte Themen