AppDelegate 永远不会为 CKQuerySubscription 调用它的 didReceiveRemoteNotification

Posted

技术标签:

【中文标题】AppDelegate 永远不会为 CKQuerySubscription 调用它的 didReceiveRemoteNotification【英文标题】:AppDelegate Never Gets Its didReceiveRemoteNotification Called For CKQuerySubscription 【发布时间】:2018-09-05 07:11:42 【问题描述】:

我正在尝试让 ios 应用监听 CKQuerySubscription 的变化。数据由远程 iOS 应用程序传输。我已经有一个 macOS 应用程序,它确实接收远程 iOS 应用程序发送的数据。我遇到问题的 iOS 应用程序已经订阅。然而,它的AppDelegate 从未收到didReceiveRemoteNotification 方法中的调用。

import UIKit
import UserNotifications
import CloudKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate 
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
        /* notifications */
        let center  = UNUserNotificationCenter.current()
        center.delegate = self
        UNUserNotificationCenter.current().getNotificationSettings  (settings) in
            switch settings.authorizationStatus 
            case .authorized:
                print("You already have permission")
                DispatchQueue.main.async() 
                    application.registerForRemoteNotifications()
                
            case .denied:
                print("setting has been disabled")
            case .notDetermined:
                print("Let me ask")
                UNUserNotificationCenter.current().requestAuthorization(options: [])  (granted, error) in
                    if error == nil 
                        if granted 
                            print("you are granted permission")
                            DispatchQueue.main.async() 
                                application.registerForRemoteNotifications()
                            
                        
                    
                
            
        
        return true
    


    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("Receiving data...") // never called...
    

我有一些能力,如下所示。我不知道应用程序是否需要push notifications。目前,它已开启。

那么为什么我的 iOS 应用没有收到远程通知调用呢?我在实际设备上使用该应用程序,而不是模拟器。谢谢。

编辑:创建对记录更改的订阅

class HomeViewController: UIViewController 
    override func viewDidLoad() 
        registerSubscription()
    

    func registerSubscription() 
        let cloudContainer = CKContainer(identifier: "iCloud.com.xxx.XXXXX")
        let privateDB = cloudContainer.privateCloudDatabase
        let predicate = NSPredicate(format: "TRUEPREDICATE")
        let subscription = CKQuerySubscription(recordType: "PrivateRecords", predicate: predicate, options: .firesOnRecordCreation)
        let notification = CKNotificationInfo()
        subscription.notificationInfo = notification
        privateDB.save(subscription, completionHandler: (returnRecord, error in
            if let err = error 
                print("Subscription has failed: \(err.localizedDescription)")
             else 
                print("Subscription set up successfully")
                print("Subscription ID: \(subscription.subscriptionID)")
            
        ))
    

【问题讨论】:

看到这个寻求帮助:***.com/questions/39382852/… @Anbu.karthik 谢谢。我看过了。 【参考方案1】:

您还可以查看更多内容。

首先,确保在您的应用委托中实现 didReceiveRemoteNotification

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any])   
  let dict = userInfo as! [String: NSObject]
  let notification = CKNotification(fromRemoteNotificationDictionary: dict)

  if let sub = notification.subscriptionID
    print("iOS Notification Received: \(sub)")
  

您还可以检查其他一些事项:

    尝试在 CloudKit 仪表板中删除您的 CKQuerySubscription,然后再次运行您的 iOS 代码来注册它。订阅是否显示在仪表板中? CloudKit 日志是否显示已发送通知?它列出了推送到设备的所有通知。 如果您使用静默推送通知,请尝试在“后台模式”功能中启用后台获取远程通知上方)。

如果你做了所有这些,它仍然不起作用,你能分享你的CKQuerySubscription代码吗?

-- 更新--

尝试在您的CKNotificationInfo 对象上设置一些附加属性。通知中有一些晦涩的错误,通常可以通过设置如下几个属性来规避:

notification.shouldSendContentAvailable = true
notification.alertBody = "" //(Yes, a blank value. It affects the priority of the notification delivery)

您也可以尝试将谓词设置为:NSPredicate(value: true)

另外,您的privateDB.save 方法返回什么?是说成功还是失败?

【讨论】:

感谢您的提示。我已经有了 didReceiveRemoteNotification 方法。对于第一名,订阅永远不会出现在 iOS 应用程序的仪表板中。它有一个用于 macOS 应用程序的。对于 2 号,macOS 对应方接收传输的数据。所以这不是一个问题。对于第 3 项,我打开和关闭了后台获取,看看它是否有任何不同。 那么听起来你的CKQuerySubscription 是问题,如果它从未出现在 CloudKit 仪表板中。您能否更新您的问题以包含您注册订阅的代码? 我刚刚更新了我的答案,尝试了更多的事情和另一个问题。 谢谢。但仪表板不会为 iOS 应用添加新订阅。如果我删除仪表板上的 macOS 应用程序并运行该应用程序,仪表板将添加一个新的。 您的privateDB.save 方法返回什么?它说它是成功还是失败?

以上是关于AppDelegate 永远不会为 CKQuerySubscription 调用它的 didReceiveRemoteNotification的主要内容,如果未能解决你的问题,请参考以下文章

iOS:最新的 Parse SDK PFFacebookUtils 块永远不会被执行

如何测试自定义 UINavigationController 行为

使用“CONTAINS”运算符时,带有 NSPredicate 的 CKQuery 失败

CloudKit:CKQuery 显示错误:错误:操作无法完成。 (CKErrorDomain 错误 1。)

executeFetchRequest 挂起并且从不返回错误或继续

CKQuery 谓词有引用而不是字段?