Swift 主从模板应用之谜

Posted

技术标签:

【中文标题】Swift 主从模板应用之谜【英文标题】:Swift Master-Detail Template App Mystery 【发布时间】:2014-06-13 03:54:36 【问题描述】:

在 Swift 中运行 Master-Detail App 的略微修改版本时,我收到 Can't unwrap Optional.None 错误。

我所做的只是将第二个 UILabel 添加到 DetailViewController,就在预先存在的 detailDescriptionLabel 下方,当我从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"
        

那么为什么我们需要在这里为detailDescriptionLabel 声明let?它从未被声明为可选标签,它像任何常规标签 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"
 

【问题讨论】:

【参考方案1】:

@IBOutlet 声明的属性总是隐式展开的可选变量。 Apple's documentation 是这样解释的:

当你在 Swift 中声明一个 outlet 时,编译器会自动 将类型转换为弱隐式解包可选并赋值 它的初始值为零。实际上,编译器替换 @IBOutlet var name: Type@IBOutlet weak var name: Type! = nil。 编译器 将类型转换为隐式展开的可选项,以便您 不需要在初始化程序中分配值。它是隐含的 解包,因为在您的课程从情节提要或 xib 文件,您可以假设插座已连接。奥特莱斯 默认情况下很弱,因为您创建的网点通常很弱 关系。

由于它是隐式展开的,因此您不必每次都必须通过 if let label = something,只要知道如果您的标签是 nil 并且您尝试使用它,您将最终出现运行时错误。我猜你的第二个标签没有连接到 Interface Builder 中——是这样吗? [OP:不!]


好的,在这种特定情况下发生的情况是,可以从主视图控制器的 prepareForSegue() 调用 configureView() 方法,因为详细视图控制器上的 detailItem 属性具有 didSet 处理程序。发生这种情况时,详细视图控制器尚未加载,因此尚未创建任何标签。由于标签将同时设置,因此您可以将两个初始化都放在该 if 语句下(甚至更清楚一点):

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"
        
    

【讨论】:

我的第二个标签绝对已连接到 Interface Builder! :-) 我像往常一样从它直接拖放到代码中,所以它肯定是挂钩的。 (我还仔细检查了 Connections Inspector。)如果我想将文本分配给我的标签,我该如何通过if let label = something 你能多贴一点代码吗?你用什么方法崩溃? (如果这更容易的话,你可以在 gist.github.com 上发布整个内容。) 确定 - 我将代码添加到我原来的问题中 - 见上文。 啊哈!不错的收获! :-) 并且非常有意义。非常有义务 - 标记为正确答案:-)

以上是关于Swift 主从模板应用之谜的主要内容,如果未能解决你的问题,请参考以下文章

模板赋值运算符重载之谜

应用内购买沙盒之谜:手机处于无法启动购买状态

为什么手机无法运行应用? Values之谜

解开Android应用程序组件Activity的"singleTask"之谜

使用 Swift 的基于文档的应用程序

我可以在主从应用程序的每个部分中拥有不同数量的行吗?