How to get data from push notification response Swift 3/iOS
Asked Answered
S

4

11

I am using the following library to generate push notifications.

https://github.com/edamov/pushok

I got the push notifications working but I don't know how to extract the response in Swift 3.

Here is what I have.

// Push notification received
    func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
        // Print notification payload data
        print("Push notification received: \(data)")

        let aps = data[AnyHashable("aps")]!

        print(aps)
    }

I can create the push notifications and the console message works but prints out this...

Push notification received: [AnyHashable("samplekey"): samplevalue, AnyHashable("aps"): {
    alert =     {
        body = hey;
        title = "Hello!";
    };
    sound = default;
}]
{
    alert =     {
        body = hey;
        title = "Hello!";
    };
    sound = default;
}

So my question is how do I access the data inside of alert for the 'body' and 'title'?

I tried accessing the variables but I keep getting errors because I'm not sure how I'm supposed to access it and could not find any documentation on this subject in any tutorials.

Sedate answered 23/3, 2017 at 20:51 Comment(1)
Can you please share Example code as i am new to push-notification in laravelKimmy
N
26

I think this is a safer way to do the way Joseph found.

guard
    let aps = data[AnyHashable("aps")] as? NSDictionary,
    let alert = aps["alert"] as? NSDictionary,
    let body = alert["body"] as? String,
    let title = alert["title"] as? String
    else {
        // handle any error here
        return
    }

print("Title: \(title) \nBody:\(body)")
Neoma answered 16/4, 2017 at 11:48 Comment(0)
B
5

I would eager you to try to find a way to avoid using force unwrapping. When you do to the following:

 let alert = aps["alert"]! as! NSDictionary
 let body = alert["body"] as! String
 let title = alert["title"] as! String

the application will crash, when any of the above values are missing.

Instead, first lets introduce a notification model.

class MTNotification {
    let alert: [String: AnyHashable]
    var title: String?
    var body: String?

    init(alert: [String: AnyHashable]) {
        self.alert = alert
    }
}

Use something to track the errors what could occur while handling the raw notification data. The better if you make it conform to the Error protocol.

enum MTError: Error {
    // Observe your transformation and extend error cases
    case missingProperty(id: String)
}

Use a helper class not to pollute the app delegate, where you can handle the transformation of the data to notifications.

class MTNotificationBuilder {

     /// Build a notification from raw data
     ///
     /// - Parameter data: Classic notification payload, received from app delegate
     /// - Returns: customized MTNotification
     /// - Throws: error while building a valid MTNotification object
    static func build(from data: [AnyHashable : Any]) throws -> MTNotification {
        guard let aps = data["aps"] as? [String: AnyHashable] else {
            // Do some error handlig
            throw MTError.missingProperty(id: "aps")
        }

        guard let alert = aps["alert"] as? [String: AnyHashable] else {
            // Do some error handlig
            throw MTError.missingProperty(id: "aps")
        }

        let notification = MTNotification(alert: alert)
        // Assign values read as optionals from alert dictionary
        notification.title = alert["title"] as? String
        notification.body = alert["body"] as? String

        return notification
    } 
}

And all you need to do at the end is to call the builder function and see the result. You can be strict and introduce errors for any of the cases, also using will help maintainability later.

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

    do {
        let notification = try MTNotificationBuilder.build(from: data)
        print(notification.alert)
    } catch let error {
        print(error)
    }
}
Beetle answered 23/3, 2017 at 23:47 Comment(1)
thanks for posting this, this does seem a lot better, giving it a try now.Sedate
E
4

Make sure you turned 'ON' Background Modes in Project 'capabilities' and checked 'Remote Notifications'. Add following method in AppDelegate class. This method will call at the time of presenting notification.

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        print(notification.request.content.userInfo)
        completionHandler([ .alert,.badge, .sound])

}
Embryogeny answered 29/1, 2018 at 12:47 Comment(0)
S
2

Okay I found out the answer. You do it like below.

let aps = data[AnyHashable("aps")]! as! NSDictionary        
let alert = aps["alert"]! as! NSDictionary
let body = alert["body"] as! String
let title = alert["title"] as! String

If someone has a more safe answer I'd appreciate them editing this or posting it.

Sedate answered 23/3, 2017 at 22:13 Comment(1)
Force unwrapping all the values is a bad idea. Make them optional like in ffabri's post is way saferAlerion

© 2022 - 2024 — McMap. All rights reserved.