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

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])

}

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)")

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)
    }
}