Swift的新手,我正在尝试理解这里的打字
我有下面的代码
@IBAction func randomImage(_ sender: Any) {
let path = Bundle.main.path(forResource: "imageList", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path!)
let data = dict!.object(forKey: "Images") as! [String]
imageView.image = UIImage(named: data.randomElement())
}
如上所示,首先我有dict!
以确保dict
可用,然后data
将被类型化为字符串数组[String]
。
现在我不明白的部分是为什么data.randomElement()
给我错误
可选类型"String?"的值必须展开为"String"类型的值
使用"?"进行聚合当可选值包含"nil"时提供默认值
使用"!"强制展开如果可选值包含"nil",则中止执行
根据建议,我可以逃脱data.randomElement()!
的惩罚,但为什么需要这样做?
randomElement()
函数返回一个Optional,因为从中提取的集合可能为空。如果是,函数将返回nil。
摆脱使用!
强制展开运算符(以及隐式展开选项等变体(的习惯我将!
称为";如果为零则崩溃";操作人员这就是它的作用。
您应该使用if let
语法(可选绑定(重写代码
@IBAction func randomImage(_ sender: Any) {
if let path = Bundle.main.path(forResource: "imageList", ofType: "plist"),
let dict = NSDictionary(contentsOfFile: path),
let data = dict.object(forKey: "Images") as? [String],
let image = UIImage(named: data.randomElement()) {
imageView.image = image
} else {
// Unable to load image
}
}
对于类似的化合物if let
,如果结果为零,则表达式在每一步都会退出。如果结果有效,它将继续执行If语句,并且新的临时变量现在是非可选的。
一旦您完成了复合if let中的最后一个let,您就可以在image
中安装一个UIImage到您的图像视图中。
如果任何步骤失败,则运行else子句。你可以在那里做任何你想做的事情——安装一个默认的映像,在imageView中安装nil来删除它,打印到控制台,等等。(尽管如果要在图像视图中安装nil图像,可以稍微简化代码。(
编辑:
除了if let
可选绑定之外,您还可以使用guard语句。
CCD_ 14任选结合表示";试着打开这个可选选项。如果成功,请创建一个仅在If语句体内部定义的变量,并执行If语句。
相反,guard
说";试着打开这个可选选项。如果成功,请继续。如果失败,请执行退出当前作用域的代码块。
当你需要检查一系列的事情,并想在一切都好的时候继续做下去,但如果出现问题,就退出。
if let
选择性结合可导致压痕水平不断增加:
func foo() {
if let a = anOpitonal {
// Do stuff
if let b = a.someOtherOptional {
// Do more stuff
if let c = b.yetAnotherOptional {
// Still more code that only runs if all 3 unwraps work
}
}
}
}
相比之下,你可以用这样的卫士来写:
func foo() {
guard let a = anOpitonal else { return }
// Do stuff
guard let b = a.someOtherOptional else { return }
// Do more stuff
guard let c = b.yetAnotherOptional else { return }
// Still more code that only runs if all 3 guard statements work
}