Swift AnyObject Conversion

时间:2016-06-05 15:29:40

标签: swift types optional downcast anyobject

我创建了一些test code以显示我遇到的问题。

这在操场上编译得很好,但是,当我尝试将其放入项目时,Xcode会在line 30上发出以下警告:Treating a forced downcast to 'String' as optional will never produce 'nil'。我有两个建议来解决这个问题:

  1. Use 'as?' to perform a conditional downcast to 'String',这完全没有意义。但是,它编译时没有警告/错误,这看起来很奇怪,因为它为非可选类型的String分配了一个可选值。

      

    当您不确定向下转换是否成功时,请使用类型转换运算符的条件形式(作为?)。这种形式的运算符将始终返回一个可选值,如果无法进行向下转换,则该值将为nil。这使您可以检查成功的向下转发。

    来自Swift language guide

    除非它认为如果转换失败(因此删除字典条目)我可能想要分配nil,这是没有意义的。特别是因为我确信它会成功,因为我只是检查它是否是String

  2. Add parentheses around the cast to silence this warning,这似乎毫无意义,但确实使警告无声。这似乎是一件奇怪的事情,但话又说回来,这可能只是一种确认你真的想要做你想做的事情的糟糕方式。

  3. 哪个选项是对的,还是两个都没有?导致此警告的原因是什么?

2 个答案:

答案 0 :(得分:6)

正确的解决方案是使用可选绑定而不是 强制解包运算符!。实际上你可以加入支票 value != nil声明中的switch

for (key, value) in dict {
    switch value {
    case let s as String:
        newDict[key] = s
    case let i as Int:
        newDict[key] = String(i)
    case let b as Bool:
        newDict[key] = b ? "1" : "0"
    case let v?:   // value is not `nil`
        newDict[key] = String(v)
    default:       // value is `nil`
        break
    }
}

答案 1 :(得分:0)

以下是您的代码,已修改以显示如何将函数结果转换为匹配AnyObject?并避免显式解包的选项:

func returnsAString() -> AnyObject? {
  return "I am a String." as? AnyObject
}

func returnsAnInt() -> AnyObject? {
  return Int(123) as? AnyObject
}

func returnsABool() -> AnyObject? {
  return true as? AnyObject
}

func returnsNilBool() -> AnyObject? {
  return nil as Bool? as? AnyObject
}

var dict    : [String : AnyObject?] = [String : AnyObject?]()
var newDict : [String : String    ] = [String : String    ]()

dict["string"] = returnsAString()
dict["int"] = returnsAnInt()
dict["bool"] = returnsABool()
dict["nil"] = returnsNilBool()

for (key, value) in dict {
    switch value {
    case let value as String:
      newDict[key] = value
    case let value as Int:
      newDict[key] = String(value)
    case let value as Bool:
      newDict[key] = (value ? "1" : "0")
    default:
      newDict[key] = "nil"
    }
}

print("Dict: \(dict)")
print("newDict: \(newDict)")

// Dict: ["nil": nil, "int": Optional(123), "bool": Optional(1), "string": Optional(I am a String.)]
// newDict: ["nil": "nil", "int": "123", "bool": "1", "string": "I am a String."]