I'm trying to extract the badge value out of the userInfo dictionary of a remote notification.
I read many post and found a solution of my problem but I'm highly not satisfied!
So here is my data structure (I removed the useless lines): { aps = { badge = 7 } }
To extract this number '7' out of my userInfo
I would like to do the following:
self.updateAppIcon(userInfo["aps"]["badge"] as? Int)
But of course I get the following error :
Swift : '(NSObject, AnyObject)' does not have a member named 'subscript'
If I'm not wrong, it's because []
returns an AnyObject which cannot be interpreted as another dictionary.
A working solution would be to do the following:
func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) {
if let aps: AnyObject = userInfo["aps"] {
if let apsDict = aps as? [String : AnyObject]{
if let badge: AnyObject = apsDict["badge"] {
self.updateAppIconBadgeNumber(badge as? Int)
}
}
}
}
func updateAppIconBadgeNumber(number: Int?) {
// do stuff here
}
But seriously... could I do it in a more sexy way ? less lines, less if clauses, less casts, etc? This is such a "code-complex" solution of an easy thing.
Thanks
The shortest one is:
// Xcode 6.0.1
func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) {
if let badge = [userInfo["aps"]?["badge"]][0] as? Int {
self.updateAppIconBadgeNumber(badge)
}
}
// Xcode 6.1
func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) {
if let badge = userInfo["aps"]?["badge"] as? Int {
self.updateAppIconBadgeNumber(badge)
}
}
?
between ["aps"]
and ["badge"]
is called "Optional Chaining".
You need this because userInfo["aps"]
can returns nil
.
And you don't have to cast it to [String : AnyObject]
because every AnyObject
has 'subscript' member.
And, Why we need [ ... ][0]
in Xcode 6.0.1 is... I don't know :( .a bug, maybe.
You could use nil coleascing operator and make it short but you may loose readability. If have a single line version of the method like this,
func handleRemoteNotification(userInfo: [NSObject : AnyObject]) {
if let badge = ((userInfo["aps"] as? [String: AnyObject]) ?? ([String: AnyObject]()))["badge"] as? Int{
self.updateAppIconBadgeNumber(badge)
}
}
You could typealias [String: AnyObject] and make it look little more readable.
typealias Dict = [String: AnyObject]
func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) {
if let badge = ((userInfo["aps"] as? Dict) ?? Dict())["badge"] as? Int{
self.updateAppIconBadgeNumber(badge)
}
}