Swift: '(NSObject, AnyObject)'没有名为'subscript'的成员。

6
我正在尝试从远程通知的userInfo字典中提取徽章值。我阅读了许多文章并找到了解决我的问题的方法,但我非常不满意!所以这是我的数据结构(我删除了无用的行):{ aps = { badge = 7 } }要从我的userInfo中提取这个数字'7',我想要执行以下操作:
self.updateAppIcon(userInfo["aps"]["badge"] as? Int)

当然,我会遇到以下错误:

Swift: '(NSObject, AnyObject)'不具有名为'subscript'的成员

如果我没记错的话,原因是[]返回一个AnyObject,无法被解释为另一个字典。

有效的解决方案是执行以下操作:

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
}

但是...我能不能以更性感的方式做到这一点?减少代码行数、if语句、强制类型转换等等?这是一个“代码复杂”的解决方案,用于简单的事情。
谢谢。
2个回答

9
最短的一个是:
// 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)
    }
}

在`["aps"]`和`["badge"]`之间的`?`被称为"可选链"。这是因为`userInfo["aps"]`可能返回`nil`,所以你需要这个。同时,不必将其转换为`[String:AnyObject]`,因为每个`AnyObject`都有`subscript`成员。
至于为什么在Xcode 6.0.1中我们需要使用`[...][0]`,我不知道 :( . 或许是一个bug。

1
非常感谢!我之前不知道有这个“可选链”,谢谢你们提供的解决方案和链接! - Kevin Delord

3
你可以使用nil合并运算符来缩短代码,但可能会降低可读性。如果有一个像这样的单行版本的方法:
func handleRemoteNotification(userInfo: [NSObject : AnyObject]) {
  if let badge = ((userInfo["aps"] as? [String: AnyObject]) ?? ([String: AnyObject]()))["badge"] as? Int{
      self.updateAppIconBadgeNumber(badge)
  }
}

你可以使用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)
    }
}

谢谢你的回答,这个方法也完美地解决了问题,但正如你所说,它不够易读。我认为@rintaro提供的答案更好。但是,你能否向我解释一下或分享一个关于这个“nil coalescing operator”“??”的链接?我不知道这是什么。 - Kevin Delord
nil coalescing operator: ??在苹果的iBook中有详细解释。我似乎无法在SO评论中使用块引用,但这里是书中直接复制的内容:nil coalescing操作符(a ?? b)如果可选项a包含一个值,则展开它,否则返回默认值b。表达式a始终是可选类型。表达式b必须匹配存储在a内部的类型。nil coalescing操作符是以下代码的简写:a != nil ? a! : b - ArtSabintsev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接