6

How to access any AnyHashable data in swift i have my data below , below is the log when i click the notification . When i click notif and when the data logs i want to print or get it so that i can load it on the view . it is already working and it log when i click the notif what i want is how to get it to load in the view.

what i have done

 guard
            let aps = userInfo[AnyHashable("aps")] as? NSDictionary,
            let alert = aps["alert"] as? NSDictionary,
            let body = alert["body"] as? String,
            let title = alert["title"] as? String
            else {
                return
        }

        print("Title: \(title) \nBody:\(body)")

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

data

[AnyHashable("aps"): {
    alert =     {
        body = "yuuu - 5.00";
        title = "New Chore!";
    };
    "content-available" = 1;
}, AnyHashable("data"): {
    chore =     {
        desc = huu;
        name = yuuu;
        pk = 125;
        reward = "5.00";
        sched = "2018-04-12T09:52:13+08:00";
    };
    "notification_id" = 16;
    pusher =     {
        publishId = "pubid-01ff965a-20af-4a58-9901-89782043d832";
    };
}]
  • You are probably dealing with a dictionary of `[AnyHashable:Any]`, but in this case it seems your keys are `String` so you should be able to access the elements via `notif["alert"]` for example – Paulw11 Apr 12 '18 at 05:59
  • you can try, let strTitle = (userInfo["aps"] as! NSDictionary).value(forKey: "notification") as! NSDictionary let title = strTitle.value(forKeyPath: "alert.title") let body = strTitle.value(forKeyPath: "alert.body") – Abhirajsinh Thakore Apr 12 '18 at 06:04
  • If i am not wrong you want to extract the received notification data right.? – Abhirajsinh Thakore Apr 12 '18 at 06:07
  • kindly post it as answer Sir so that can upvote. Thanks –  Apr 12 '18 at 06:08
  • @AbhirajsinhThakore , yes exactly –  Apr 12 '18 at 06:08
  • @DurnKurvirck please check the Answer. And if it helped Approve that – Abhirajsinh Thakore Apr 12 '18 at 06:09
  • https://stackoverflow.com/questions/39864381/how-can-i-access-anyhashable-types-in-any-in-swift see this post or https://stackoverflow.com/questions/46294715/swift-3-0-how-can-i-access-anyhashable-types-in-any-in-swift-3 – Wings Apr 12 '18 at 06:17
  • Thanks for the idea , to all fo you –  Apr 12 '18 at 06:19

3 Answers3

7

You can Possibly Try:

Update for Swift 5+:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
    guard let arrAPS = userInfo["aps"] as? [String: Any] else { return }
    if application.applicationState == .active{
        guard let arrAlert = arrAPS["alert"] as? [String:Any] else { return }

        let strTitle:String = arrAlert["title"] as? String ?? ""
        let strBody:String = arrAlert["body"] as? String ?? ""

        let alert = UIAlertController(title: strTitle, message: strBody, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Ok", style: .default) { action in
            print("OK Action")
        })
        self.window?.rootViewController?.present(alert, animated: true)
    } else {
        guard let arrNotification = arrAPS["notification"] as? [String:Any] else { return }
        guard let arrAlert = arrNotification["alert"] as? [String:Any] else { return }

        let strTitle:String = arrAlert["title"] as? String ?? ""
        print("Title --", strTitle)
        let strBody:String = arrAlert["body"] as? String ?? ""
        print("Body --", strBody)
    }
}

Swift 2+ :

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {

    guard let dictAPS = userInfo["aps"] as? NSDictionary else { return }

    if application.applicationState == .active{
        let title = dictAPS.value(forKeyPath: "alert.title")
        let body = dictAPS.value(forKeyPath: "alert.body")
        let alert = UIAlertController(title: "\(title!)", message: "\(String(describing: body))", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Ok", style: .default) { action in
                   })
        self.window?.rootViewController?.present(alert, animated: true)
    }else{
        guard let dictNoti = dictAPS.value(forKey: "notification") as? NSDictionary else { return }
        let title = dictNoti.value(forKeyPath: "alert.title")
        print(title)
        let body = dictNoti.value(forKeyPath: "alert.body")
        print(body)
    }
}
Abhirajsinh Thakore
  • 1,806
  • 2
  • 13
  • 23
  • You can try: let strData = (userInfo["data"] as! NSDictionary) let desc = strData.value(forKeyPath: "chore.desc") let name = strData.value(forKeyPath: "chore.name") let pk = strData.value(forKeyPath: "chore.pk") let reward = strData.value(forKeyPath: "chore.reward") let sched = strData.value(forKeyPath: "chore.sched") – Abhirajsinh Thakore Apr 12 '18 at 06:23
  • but i want to trigger it only when notification is tap –  Apr 12 '18 at 06:24
  • This Method will be called On tap:, func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { //Your code to handle events } – Abhirajsinh Thakore Apr 12 '18 at 06:43
  • Invalid redeclaration of 'userNotificationCenter(_:didReceive: –  Apr 12 '18 at 06:45
  • do the things inside that, I guess this is only called when tapped on notification. – Abhirajsinh Thakore Apr 12 '18 at 06:48
  • Actually Sir i can receieved notif in foreground or background , what i want is that hash data will only be printed or i want to only get the data when notification is tapped. –  Apr 12 '18 at 06:55
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/168791/discussion-between-durn-kurvirck-and-abhirajsinh-thakore). –  Apr 12 '18 at 07:00
  • I ma getting the following error on executing the above code. 2018-07-25 15:30:06.418783+0530 ping[1544:337964] XPC connection interrupted Could not cast value of type '__NSCFString' (0x3880c020) to 'NSDictionary' (0x3880c73c). 2018-07-25 15:30:08.487272+0530 ping[1544:337834] Could not cast value of type '__NSCFString' (0x3880c020) to 'NSDictionary' (0x3880c73c). – Saurabh Jul 25 '18 at 10:10
2

anwer : on how to load notif data when notif is tap

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

        let userInfo = response.notification.request.content.userInfo
        // Print message ID.
        if let messageID = userInfo["gcmMessageIDKey"] {
            print("Message ID: \(messageID)")
        }
        switch response.actionIdentifier {
        case "action1":
            print("Action First Tapped")
        case "action2":
            print("Action Second Tapped")
        default:
            break
        }

        // Print full message.
        print(userInfo)
        Messaging.messaging().appDidReceiveMessage(userInfo)
        completionHandler()
    }
0

APS data can be checked as below. You can check each keys as below to avoid crashing app if particular key is not available in notification data and handle accordingly.

if (userInfo["aps"] as? [String:Any]) != nil {
   if let data = userInfo["data"] as? String{
      if let desc = userInfo["desc"] as? String {
          //Access variable desc here...
          print(desc)
      } 
   }
}
Apurv Soni
  • 51
  • 1
  • 5
  • but how to trigger it only when user tap the notification –  Apr 12 '18 at 06:26
  • Below method will be called when user taps on notification when App is in background or closed - application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) In case of App in foreground you can manage notification by UserNotificationCenter methods and delegates. – Apurv Soni Apr 12 '18 at 06:32
  • i only want to get and print the data when notifcation is tapped –  Apr 12 '18 at 06:37
  • Okay. When app is in background or launched from Push notification you will get data in “didReceiveRemoteNotification” method and incase of application is running notification will not be displayed if you have not managed it using “UserNotificationCenter”. In later case you will get notification data in “userNotificationCenter didReceive response: UNNotificationResponse” method. Use above code to handle it – Apurv Soni Apr 12 '18 at 06:46
  • Actually Sir i can receieved notif in foreground or background , what i want is that hash data will only be printed or i want to only get the data when notification is tapped. –  Apr 12 '18 at 06:55
  • when notif is open. –  Apr 12 '18 at 06:55
  • 1
    Above mentioned methods will called only when notification is tapped. – Apurv Soni Apr 12 '18 at 07:04
  • i have got the answer sir i have provided it above. –  Apr 12 '18 at 07:05