Swift读取远程通知的userInfo

Posted

技术标签:

【中文标题】Swift读取远程通知的userInfo【英文标题】:Swift read userInfo of remote notification 【发布时间】:2015-02-18 23:56:52 【问题描述】:

当我收到这样的远程通知时,我实现了一个打开 AlertView 的功能:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
        var notifiAlert = UIAlertView()
        var NotificationMessage : AnyObject? =  userInfo["alert"]
        notifiAlert.title = "TITLE"
        notifiAlert.message = NotificationMessage as? String
        notifiAlert.addButtonWithTitle("OK")
        notifiAlert.show()

但 NotificationMessage 始终为零。

我的 json 有效负载如下所示:

"aps":"alert":"Testmessage","badge":"1"

我正在使用 Xcode 6、Swift 并且正在为 ios8 进行开发。 我现在搜索了几个小时,但没有找到任何有用的信息。 通知工作得很好..如果我点击它,警报视图就会打开。 我的问题是,我无法从 userInfo 中获取数据。

【问题讨论】:

【参考方案1】:

userInfo 字典的根级项是"aps",而不是"alert"

尝试以下方法:

if let aps = userInfo["aps"] as? NSDictionary 
    if let alert = aps["alert"] as? NSDictionary 
        if let message = alert["message"] as? NSString 
           //Do stuff
        
     else if let alert = aps["alert"] as? NSString 
        //Do stuff
    

见Push Notification Documentation

【讨论】:

这在客观 C++ 中看起来如何? 很高兴您已经通知 OP 根级别项目是 aps 而不是在 userInfo dic 中提醒 .... 但是如何找出 iOS 中的正确键和字典结构系统发送通知 userInfo 字典。在 swift 4 文档中,我可以看到 Notification.Name 中所有标准化的通知名称,但我看不到任何文档说...这是随特定通知发送的 userInfo 字典,这里是键..? 是否可以在aps中添加更多参数?【参考方案2】:

斯威夫特 5

struct Push: Decodable 
    let aps: APS
    
    struct APS: Decodable 
        let alert: Alert
        
        struct Alert: Decodable 
            let title: String
            let body: String
        
    
    
    init(decoding userInfo: [AnyHashable : Any]) throws 
        let data = try JSONSerialization.data(withJSONObject: userInfo, options: .prettyPrinted)
        self = try JSONDecoder().decode(Push.self, from: data)
    

用法:

guard let push = try? Push(decoding: userInfo) else  return 
let alert = UIAlertController(title: push.aps.alert.title, message: push.aps.alert.body, preferredStyle: .alert)

【讨论】:

【参考方案3】:

方法(Swift 4):

func extractUserInfo(userInfo: [AnyHashable : Any]) -> (title: String, body: String) 
    var info = (title: "", body: "")
    guard let aps = userInfo["aps"] as? [String: Any] else  return info 
    guard let alert = aps["alert"] as? [String: Any] else  return info 
    let title = alert["title"] as? String ?? ""
    let body = alert["body"] as? String ?? ""
    info = (title: title, body: body)
    return info

用法:

let info = self.extractUserInfo(userInfo: userInfo)
print(info.title)
print(info.body)

【讨论】:

【参考方案4】:

对我来说,当我从Accengage 发送消息时,以下代码有效 -

private func extractMessage(fromPushNotificationUserInfo userInfo:[NSObject: AnyObject]) -> String? 
    var message: String?
    if let aps = userInfo["aps"] as? NSDictionary 
        if let alert = aps["alert"] as? NSDictionary 
            if let alertMessage = alert["body"] as? String 
                message = alertMessage              
            
        
    
    return message

与 Craing Stanford 的答案的唯一区别是 key 我用来从 alert 实例中提取消息的 body 是不同的。请参阅下文了解更多信息 -

if let alertMessage = alert["message"] as? NSString

if let alertMessage = alert["body"] as? String

【讨论】:

【参考方案5】:

这是我的 objC 版本

if (userInfo[@"aps"])
    NSDictionary *aps = userInfo[@"aps"];
    if (aps[@"alert"])
        NSObject *alert = aps[@"alert"];
        if ([alert isKindOfClass:[NSDictionary class]])
            NSDictionary *alertDict = aps[@"alert"];
            if (alertDict[@"message"])
                NSString *message = alertDict[@"message"];
            
        
        else if (aps[@"alert"])
            NSString *alert = aps[@"alert"];
        
    

【讨论】:

【参考方案6】:

应在应用处于活动状态时显示警报。所以检查状态是否处于活动状态。

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) 
    if application.applicationState == .active 
      if let aps = userInfo["aps"] as? NSDictionary 
        if let alertMessage = aps["alert"] as? String 
          let alert = UIAlertController(title: "Notification", message: alertMessage, preferredStyle: UIAlertControllerStyle.alert)
          let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
          alert.addAction(action)
          self.window?.rootViewController?.present(alert, animated: true, completion: nil)
        
      
    
    completionHandler(.newData)
  

如果用户需要消息,那么他可以从这里得到警报消息。

【讨论】:

【参考方案7】:

我使用 APNs Provider 和 json payload 如下


  "aps" : 
    "alert" : 
      "title" : "I am title",
      "body" : "message body."
    ,
  "sound" : "default",
  "badge" : 1
  

由于提供者将其作为 JSON 定义的字典生成,iOS 将其转换为 NSDictionary 对象,没有 Dictionary 之类的下标,但可以使用 value(forKey:)

来自here的参考

这是我为 Swift 4 设计的方式

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) 
    guard application.applicationState == .active else  return 
    guard let alertDict = ((userInfo["aps"] as? NSDictionary)?.value(forKey: "alert")) as? NSDictionary,
        let title = alertDict["title"] as? String,
        let body = alertDict["body"] as? String
        else  return 
    let alertController = UIAlertController(title: title, message: body, preferredStyle: .alert)
    let okAct = UIAlertAction(title: "Ok", style: .default, handler: nil)
    alertController.addAction(okAct)
    self.window?.rootViewController?.present(alertController, animated: true, completion: nil)
    completionHandler(UIBackgroundFetchResult.noData)

【讨论】:

以上是关于Swift读取远程通知的userInfo的主要内容,如果未能解决你的问题,请参考以下文章

从通知中心删除远程通知

火力基地 |远程通知不显示,swift 3.0

在 Swift 中注册远程通知时未收到设备令牌

远程通知中的自定义声音 iOS 10,swift 3

Swift:如何从服务器接收远程通知?

Swift 清除特定的远程通知