【问题标题】:launchOptions always nil when launching from a push notification从推送通知启动时,launchOptions 始终为零
【发布时间】:2020-01-31 16:26:21
【问题描述】:

我正在从 Django 应用(使用 django-push-notifications)向 iOS 应用发送推送通知。该应用程序针对 iOS 13,我在运行 iOS 13.3.1 的 iPhone 7 上运行它。我在 Xcode 11.3.1 中调试

我正在尝试两种不同的方法从 Django 端发送通知:

方法一:

devices.send_message(message={"title" : title, "body" : message}, thread_id="events", extra={"foo": "bar"})

方法二:

devices.send_message("[will be overwritten]", extra={
    "aps": {
        "alert": {
            "title": "Bold text in the notification",
            "body": "Second line in the notification"
        },
        "sound": "default",
    },
    "foo": "bar"
})

据我所知,这两种方法都会产生类似于方法 2 的有效负载。

我正在通过以下方式进行调试:

  1. 在我的设备方案中设置“等待启动可执行文件”
  2. 在 Xcode 中构建和运行
  3. 确保应用程序已在任务切换器中被终止
  4. 触发发送远程通知
  5. 点击收到的通知以启动应用程序

无论我做什么,launchOptions 总是为零。我尝试设置断点来检查变量。如果launchOptions 不为零,我尝试使用os_log 登录到控制台,并且我尝试触发警报(遵循this question 的建议)以排除Xcode 调试器干扰。它总是为零。

我的 AppDelegate 目前看起来像这样:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    let notificationOption = launchOptions?[.remoteNotification]

    let alert = UIAlertController(title: "Your title", message: notificationOption.debugDescription, preferredStyle: .alert)
    let cancel = UIAlertAction(title: "Cancel", style: .default, handler: { action in
    })
    alert.addAction(cancel)
    DispatchQueue.main.async(execute: {
        application.windows.first!.rootViewController?.present(alert, animated: true, completion: nil)

    })
    return true
}

警报触发,但警报内容只是读取“nil”。

我无法弄清楚缺少什么。我的通知有效负载可能与我认为的不完全一样(我已经在 Github 页面上询问 django-push-notifications 以确认这方面是否存在问题)。也有可能我错过了设置远程通知的步骤,但我确实收到了通知,并且它们按我预期的方式显示,所以它们似乎在工作。

非常感谢任何建议!

【问题讨论】:

  • 您是如何设置项目的,以便我们可以通过重现您的步骤来提供帮助?
  • 我不确定我是否知道您的要求。 iOS 应用程序是使用 Xcode 中的标准“选项卡式应用程序”模板设置的。它对 UI 使用 SwiftUI,对 HTTP 请求使用 Alamofire,除了它只使用标准的 iOS SDK 功能。 AppDelegate 是按照我分享的方式设置的。后端是 Django 2.2.9,使用我共享的 API 调用处理 APNS 调用的 Django-push-notifications。我正在为 APNS 使用开发证书并在本地运行服务器。我触发了从我的网络应用程序发送通知。
  • 我不知道这是否适用于您的特定情况,因为我没有专门使用通知,但我正在处理从关联文件启动的应用程序的一个非常相似的问题针对 iOS 13 的类型,我最终发现在 iOS 13 中,很多东西都从 AppDelegate 转移到了 SceneDelegate。所以你可以做一些研究,看看是否适合你。您在网上找到的大多数示例代码都使用 AppDelegate,因为它们是在 iOS 13 之前编写的,这让我很困惑。
  • 感谢@vikingmobile,我开始怀疑Apple 可能已经改变了一些东西并且没有告诉任何人(而且由于很少有人针对iOS 13,所以没有多少人会注意到)。我找到了解决方法(见下文),但如果解决方法导致问题,我会尝试 SceneDelegate。

标签: ios swift apple-push-notifications ios13


【解决方案1】:

在 iOS 13.0 中,当应用程序被杀死时,如果您点击通知,想要打开应用程序并获取通知负载。这是你的做法。

请检查sceneDelegate下的connectOptions

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//look for remote notification response
   if let response = connectionOptions.notificationResponse{
        print(response.notification.request.content.userInfo)
   }

   guard let _ = (scene as? UIWindowScene) else { return }
} 

【讨论】:

  • 很高兴我找到了这个答案。对我帮助很大。谢谢。
  • iOS 14 也会发生这种情况。*
【解决方案2】:

我没有找到解决此问题的方法,但我找到了解决方法。我仍然不知道为什么 launchOptions 总是为零,但我已经能够通过执行以下操作来访问有效负载:

在 AppDelegate.swift 中:

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

...

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        UNUserNotificationCenter.current().delegate = self
        return true
    }

...

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let actionIdentifier = response.actionIdentifier

        switch actionIdentifier {
        case UNNotificationDismissActionIdentifier: // Notification was dismissed by user
            // Do something
            completionHandler()
        case UNNotificationDefaultActionIdentifier: // App was opened from notification
            // Do something
            completionHandler()
        default:
            completionHandler()
        }
    }

如果我在 userNotificationCenter 中设置断点,我可以挖掘出通知负载:

【讨论】:

【解决方案3】:

似乎在 iOS 13 发生变化后,我们不必在 didFinishLaunchingWithOptions 函数中处理通知。

我们可以使用:

extension AppDelegate: UNUserNotificationCenterDelegate{
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        let userInfo = response.notification.request.content.userInfo

        if let aps = userInfo["aps"] as? [String: AnyObject] {
            // Do what you want with the notification
        }

      completionHandler()
    }
}

当用户点击通知时,它适用于任何场景。

【讨论】:

  • 您肯定会接到userNotificationCenter(_:didReceive:withCompletionHandler 的电话,但是从iOS10 开始就可以使用,如果您说的是正确的,那么为什么Apple 仍然提供remotenotification 作为启动选项?此外,您的答案与一个月前给出的其他答案有何不同?
  • 不确定这是错误还是功能,但似乎当您将配置与 SceneDelegate (>iOS 13) 一起使用时,当您的应用程序从通知初始启动时,启动选项为零。跨度>
  • 我就是不知道。我是根据文档为您提供信息。只是为了清楚地听到,你是说你在 iOS 13 之前得到了 launchOptions 吗?还是只是猜测?
  • 我可以确认在 iOS 13 之前启动选项不为零
  • 是的,在 iOS 13 之前的启动选项不是零。官方文档中对此没有任何内容,但是在切换到 iOS 13 并配置 SceneDelegate 后,从通知中获取有关打开应用程序的信息的唯一方法是使用 UNUserNotificationCenterDelegate。也许这只是一个很快就会修复的错误,但很高兴知道。我花了一整天的时间寻找解决方案,所以也许我的回答会对某人有所帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-12
  • 2014-05-02
  • 2014-12-16
  • 2023-03-09
  • 2013-10-09
  • 2019-10-13
相关资源
最近更新 更多