2017-06-14 2 views
1

Ich habe ein CloudKit-Abonnement für eine bestimmte Klasse erstellt, die eine Push-Benachrichtigung bei der Objekterstellung oder Aktualisierung auslöst.iOS - Push-Benachrichtigungen reagieren nicht wie erwartet

Dieser Code geht wie folgt vor:

// Create the predicate 
let predicate = NSPredicate(format: "recordId = %@", RECORD_ID) 

// Create a subscription specifying the record type, predicate and notification options 
let subscription = CKQuerySubscription(recordType: "Notes", predicate: predicate, options: [.firesOnRecordUpdate, .firesOnRecordCreation]) 

// Create a CloudKit notification object 
let notificationInfo = CKNotificationInfo() 
notificationInfo.shouldBadge = true 

// Set the subscriptor's notification object to the new CloudKit notification object 
subscription.notificationInfo = notificationInfo 

// Save the subscription to the database 
let publicDatabase = CKContainer.default().publicCloudDatabase 
publicDatabase.save(subscription) { (subs, err) in 
    if let err = err { 
     print("Failed to save subscription:", err) 
     return 
    } 
} 

Das Abonnement erfolgreich auf dem Server gespeichert wird.

Ich wollte eine stille Benachrichtigung erstellen, und ich bin Umgang mit der Meldung wie folgt (beim Empfang):

import UserNotifications 

// Register for push notifications 
let notificationCenter = UNUserNotificationCenter.current() 
notificationCenter.requestAuthorization(options: [.badge, .alert, .sound]) { (success, err) in 
    if let err = err { 
     print("Failed to request oauth for notifications:", err) 
    } 
} 
application.registerForRemoteNotifications() 

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { 
    print("didRegisterForRemoteNotificationsWithDeviceToken:", deviceToken) 
} 

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { 
    print("Failed to register notifications_ error:", error) 
} 

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { 
    print("------------------------") 
    print("Receiving updates from the server") 

    // Convert the userInfo parameter to a CKNotification object 
    let cloudKitNotification = CKNotification(fromRemoteNotificationDictionary: userInfo) 

    // Get the body of the notification 
    let alertBody = cloudKitNotification.alertBody 
    print("alertBody:", alertBody ?? "") 

    // Get the new or modified record form the CKQueryNotification object 
    if cloudKitNotification.notificationType == CKNotificationType.query { 
     guard let queryNotification = cloudKitNotification as? CKQueryNotification else { 
      print("could not cast the query notification") 
      return 
     } 
     let recordId = queryNotification.recordID 
     print("recordId:", recordId ?? "") 
    } 
} 

Hier ist, wo das Problem auftritt.

Wenn ich die App verwende und ein Update an den Server gesendet wurde, wird meine didReceiveRemoteNotification ausgelöst und alles funktioniert ordnungsgemäß. Wenn sich meine App jedoch im Hintergrund befindet, ändert sich mein app_notification-Badge (erhöht um 1) bei einer Push-Benachrichtigung wird empfangen, aber die didReceiveRemoteNotification feuert nicht.

Meine Frage ist, wie kann ich den Push-Notification-Eintrag behandeln, wenn es ankommt?

ich die Required background modes in der Info.plis Datei gesetzt haben mit App downloads content from the network und App downloads content in response to push notifications

Eine weitere Sache, bemerkte ich, wenn ich auf meine notificationInfo.shouldBadge gesetzt falsch ich keine Push-Benachrichtigungen erhalten.

Vielen Dank für

helfen
+0

Gibt es Hinweise, wie Sie dieses Problem umgehen können? –

Antwort

1

Benachrichtigungen werden nicht ankommen, vor allem, wenn der Benutzer geht in den Flugmodus, verliert die Verbindung garantiert, etc. Und, auch wenn Sie die Ankündigung tun erhalten, wenn Ihre Anwendung ausgeführt wird, können Sie Führen Sie keine Verarbeitung aus. Das bedeutet, dass Sie jedes Mal, wenn Sie die App starten, davon ausgehen müssen, dass noch Benachrichtigungen für die Verarbeitung vorliegen (die, die Sie erhalten haben, während Sie nicht in der App waren, sowie solche, für die Sie aus irgendeinem Grund keine Push-Benachrichtigung erhalten haben).

Also, wenn Sie die App starten, müssen Sie eine ausgeben und suchen Sie nach neuen Benachrichtigungen, die Sie noch nicht verarbeitet haben.

Sie erstellen die CKFetchNotificationChangesOperation Operation, und legen Sie die notificationChangedBlock. Dieser Block wird einmal für jede vom Server abgerufene Benachrichtigung aufgerufen. Sie können auswerten, ob es bereits als "gelesen" markiert ist. Wenn nicht, dann behandeln Sie es, wie Sie normalerweise in didReceiveRemoteNotification tun.

Optional können Sie auch Code in fetchNotificationChangesCompletionBlock festlegen, der am Ende des Vorgangs einmal ausgelöst wird, nachdem alle Benachrichtigungen vom Server abgerufen wurden.

+0

Also sagen wir mal. Ich hatte 3 Push-Benachrichtigungen für eine Benutzerprofildatenaktualisierung ausstehend. Wenn ich die App auf einem anderen Gerät eintrage und nach ausstehenden OPs suche, wird es sagen, dass ich 3 ausstehende OP habe. Ich kann überprüfen lassen, sagen wir nach seiner subscriptionID, und wenn sie alle gleich sind, kann ich nur die neueste abholen, oder? Denkst du in diesem Fall, dass ich stattdessen 'fetchNotificationChangesCompletionBlock' verwenden soll, um den neuesten zu holen? Es gibt bestimmte Fälle, in denen ein Abonnement nur für einen bestimmten Typ gilt, so dass ich nicht alle durchlaufen muss. –

+0

Ich verstehe, was Sie sagen. Ich glaube, Sie müssen immer noch durch den notificationCangedBlock iterieren, denn wenn Sie diese Completion-Blöcke betrachten, ist das der einzige, der das Notificat tatsächlich empfängt.Die Notifikationen werden nicht in den finalen Abschlussblock übernommen, Sie müssen sie also selbst abholen. Zwei Dinge, die Ihnen helfen werden: Die Benachrichtigungen, die Sie im ersten Block erhalten, werden als gelesen/ungelesen markiert (vorausgesetzt, Sie aktualisieren den Status bei der Verarbeitung), so dass Sie die vergangenen Nachrichten fortsetzen können. Zweitens, dass – Thunk

+0

... Operation kann mit einem Change-Token initiiert werden, die im Grunde der "Lesezeiger" angibt, wie weit Sie zuvor gelesen haben. Wenn Sie also das Änderungs-Token jedes Mal speichern und nachfolgende Anrufe mit dem letzten Token starten, das Sie erhalten haben, sollten Sie die Anzahl der Benachrichtigungen, die Sie durchlaufen müssen, eingrenzen. Aber ich kenne keinen Weg, einfach nur den absolut letzten zu fassen. – Thunk

Verwandte Themen