到目前为止,我一直在Swift 2.1中解包Optionals:
@IBOutlet var commentTextView: UITextView!
if let comment = user["comment"] as? String {
commentTextView.text = comment
}
我从未真正考虑过这个问题,但我认为我这样做的原因是因为我担心如果user["comment"]
返回String
以外的其他内容,这句话会引发错误:
commentTextView.text = user["comment"] as? String
如果user["comment"]
不是String
,是否会分配赋值运算符左侧的变量并抛出错误或者是否会跳过赋值?
答案 0 :(得分:1)
我猜user
实际上是字典[String: Any]
, 对if let comment = user["comment"] as? String { ... }
做的事情不只是展开可选项而是展开conditional type casting (然后解开它的可选结果):
当您不确定向下转换是否成功时,请使用类型转换运算符(
as?
)的条件形式。这种形式的运算符将始终返回一个可选值,如果无法进行向下转换,则该值将为nil
。这使您可以检查成功的向下转发。
现在,要回答您的问题,如果user["comment"]
不是String
,那么结果将是commentTextView.text
将被分配nil
值,这很糟糕因为它的类型是String!
(implicitly unwrapped optional),我们承诺它将永远为nil
。所以,是的,会有一个错误,实际上是一个例外,但不会出现在你想要它的地方,但是当你的应用程序试图访问它的值时,假设它不会是{{ 1}}。
你应该做什么取决于特定情况。
E.g。如果你可以让nil
成为像user
这样的字典,那么你就可以真正地解开选项并使用[String: String]
之类的东西。或者,如果您完全确定if let comment = user["comment"] { ... }
键的值总是,那么您可以"comment"
。
但如果那不可能,那么你必须坚持使用向下投射,而你唯一能做的就是使用它的强制形式,即let comment = user["comment"]!
。如果commentTextView.text = user["comment"] as! String
的值恰好不是"comment"
而是其他值,那么这个至少会在现场产生例外。
答案 1 :(得分:0)
nil
将被分配给变量。
如果变量的类型是非可选的,那么您将收到运行时错误。
但是,如果user["comment"]
一个String
,您将收到有关丢失!
或?
的编译错误。
答案 2 :(得分:0)
首先我们需要知道字典“user”是什么类型。
我认为它是[String:AnyObject]之类的未知类型,否则你为什么要尝试将它作为String展开。让我们写一个简短的测试来看看会发生什么:
let dict: [String: AnyObject] = ["SomeKey" : 1]
if let y = dict["SomeKey"] as? String {
print(y)
}
您可以清楚地看到“SomeKey”的值是一个整数。尝试将其解包为String时不会触发错误,只会跳过“if”语句。如果实际发生的赋值很难证明(可能通过查看汇编代码),因为变量“y”在if语句之后根本不存在。我认为它根本不会被创建。
如果字典的类型被称为[String:String],您可以省略尝试将其作为String展开,因为它总是清楚该类型是String。
let dict2: [String: String] = ["SomeKey" : "SomeValue"]
if let y = dict2["WrongKey"] {
// In this case print(y) will not be called because the subscript operator of the dictionary returns nil
print(y)
}
// In this case print(y) will be called because the key is correct
if let y = dict2["SomeKey"] {
print(y)
}