我在Swift中运行稍微修改过的Master-Detail App版本时出现Can't unwrap Optional.None
错误。
我所做的就是在 DetailViewController 中添加第二个UILabel
,在预先存在的detailDescriptionLabel
下面,当我导航到 DetailViewController 来自 MasterViewController 我在设置新标签的语句上崩溃:
secondLabel.text = "This is the Second Label"
我声明这个标签如下:
@IBOutlet var secondLabel : UILabel
真正有趣的是,用于设置detailDescriptionLabel
的预先存在的代码包含新的可选let
语法:
if let label = self.detailDescriptionLabel {
label.text = "This is the Detail View"
}
那么为什么let
需要detailDescriptionLabel
声明?它从未被声明为可选标签,它被声明为任何常规的标签IBOutlet属性,如下所示:
@IBOutlet var detailDescriptionLabel: UILabel
那为什么它被视为可选?
这是否意味着从现在起我作为IBOutlet添加的任何对象如果我想通过代码设置它还必须通过这种let
语句?
修改
我在anotherLabel.text = "Second Label"
行上的以下方法崩溃了:
func configureView() {
// Update the user interface for the detail item.
if let theCar: CarObject = self.detailItem as? CarObject {
if let label = self.detailDescriptionLabel {
label.text = theCar.make
}
anotherLabel.text = "Second Label"
}
}
但是当我将整个anotherLabel
业务视为if let
时,如下所示,它的效果非常好:
if let label2 = self.anotherLabel {
label2.text = "Second Label"
}
答案 0 :(得分:4)
使用@IBOutlet
声明的属性始终是隐式解包的可选变量。 Apple's documentation以这种方式解释:
当您在Swift中声明一个插座时,编译器会自动生成 将类型转换为弱隐式解包的可选和分配 它的初始值为零。实际上,编译器会替换
@IBOutlet var name: Type
@IBOutlet weak var name: Type! = nil
if let label = something
。 编译器 将类型转换为隐式展开的可选项以便您 不需要在初始化程序中分配值。这是隐含的 解开因为你的课程从故事板或故事板初始化后 xib文件,您可以假设插座已连接。奥特莱斯 默认情况下很弱,因为你创建的网点通常很弱 关系。
由于它是隐式展开的,因此您不必 每次都要通过nil
,只要知道您的标签是configureView()
并且你尝试使用它,你最终会遇到运行时错误。我猜你的第二个标签并没有在Interface Builder中连接 - 是这样的吗? [OP:没有!]
好的,在这种特定情况下发生的事情是prepareForSegue()
方法可以从主视图控制器detailItem
调用,因为didSet
属性在详细视图控制器上有一个func configureView() {
// Update the user interface for the detail item.
if let theCar: CarObject = self.detailItem as? CarObject {
if self.detailDescriptionLabel != nil {
self.detailDescriptionLabel.text = theCar.make
self.secondLabel.text = "Second Label"
}
}
}
处理程序。发生这种情况时,尚未加载详细视图控制器,因此未创建任何标签。由于标签将同时设置,您可以将两个初始化放在if if语句下(并使其更清晰,甚至):
{{1}}