Swift read userInfo of remote notification

The root level item of the userInfo dictionary is "aps", not "alert".

Try the following:

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

See Push Notification Documentation


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

Usage:

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

Method (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
}

Usage:

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