Swift:'(NSObject,AnyObject)'没有名为'下标'的成员

时间:2023-01-12 16:10:04

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!

我正在尝试从远程通知的userInfo字典中提取徽章值。我阅读了很多帖子并找到了我的问题的解决方案,但我非常不满意!

So here is my data structure (I removed the useless lines): { aps = { badge = 7 } }

所以这是我的数据结构(我删除了无用的行):{aps = {badge = 7}}

To extract this number '7' out of my userInfo I would like to do the following:

要从我的userInfo中提取此数字'7',我想执行以下操作:

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'

Swift:'(NSObject,AnyObject)'没有名为'下标'的成员

If I'm not wrong, it's because [] returns an AnyObject which cannot be interpreted as another dictionary.

如果我没错,那是因为[]返回一个不能被解释为另一个字典的AnyObject。

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

2 个解决方案

#1


9  

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.

?在[“aps”]和[“badge”]之间称为“可选链接”。你需要这个,因为userInfo [“aps”]可以返回nil。而且你不必将它转换为[String:AnyObject],因为每个AnyObject都有'subscript'成员。

And, Why we need [ ... ][0] in Xcode 6.0.1 is... I don't know :( .a bug, maybe.

而且,为什么我们在Xcode 6.0.1中需要[...] [...]是......我不知道:(。一个bug,也许吧。

#2


3  

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,

您可以使用nil coleascing运算符并缩短它但可能会失去可读性。如果有这样的方法的单行版本,

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 [String:AnyObject]并使其看起来更具可读性。

typealias Dict = [String: AnyObject]
func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) {
    if let badge = ((userInfo["aps"] as? Dict) ?? Dict())["badge"] as? Int{
        self.updateAppIconBadgeNumber(badge)
    }
}

#1


9  

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.

?在[“aps”]和[“badge”]之间称为“可选链接”。你需要这个,因为userInfo [“aps”]可以返回nil。而且你不必将它转换为[String:AnyObject],因为每个AnyObject都有'subscript'成员。

And, Why we need [ ... ][0] in Xcode 6.0.1 is... I don't know :( .a bug, maybe.

而且,为什么我们在Xcode 6.0.1中需要[...] [...]是......我不知道:(。一个bug,也许吧。

#2


3  

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,

您可以使用nil coleascing运算符并缩短它但可能会失去可读性。如果有这样的方法的单行版本,

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 [String:AnyObject]并使其看起来更具可读性。

typealias Dict = [String: AnyObject]
func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) {
    if let badge = ((userInfo["aps"] as? Dict) ?? Dict())["badge"] as? Int{
        self.updateAppIconBadgeNumber(badge)
    }
}