首页 > 解决方案 > 将 UIContainerView 嵌入到表视图中并尝试通过 @IBOutlet 访问导致 Unexpectedly found nil

问题描述

使用Apple 相当古老的 Swift Getting Started教程作为基础,我有一个可以工作的应用程序。我想在表格顶部添加一个 UIView,以在发生错误时临时显示。不幸的是,当尝试从 UIView 的关联类访问 UI 元素时,我收到“在隐式展开可选值时意外发现 nil”错误。

https://imgur.com/wfqFach.png

这实际上是一个 UIContainerView,但显然是以 UIView 的形式出现的。

我已经将UIView链接视图(通过嵌入 segue)子类化为一个名为 ErrorView 的子类,并在表视图的子类中添加了一个指向 UIView 的@IBOutlet 链接。UI 元素通过@IBOutlet 链接到ErrorView 类。

当通过表子类中的 @IBOutlet 访问 ErrorView 类成员时,一切都很花哨,直到 ErrorView 类尝试访问其 @IBOutlet 链接元素,此时它崩溃并显示“在隐式解包 Optional 值时意外发现 nil”。

奇怪的是,从错误类中访问视图本身是可能的,因此我可以做一些与视图相关的事情,比如在没有错误的情况下改变它的颜色——尽管颜色改变实际上并没有发生。

下面是一个非常精简的代码版本,它应该会重现该问题。

我正在使用 iOS13 和 Xcode 11 测试版。

错误视图.swift

import UIKit

class ErrorView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    @IBOutlet weak var uiMessage: UILabel!

    func setErrorMessage(errorMessage: String){
         uiMessage.text=errorMessage       //<-- error here
    }
}

模块表视图控制器

import UIKit
import Foundation

class ModuleTableViewController: UITableViewController {
 @IBOutlet weak var errorView: ErrorView!

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        errorView.setErrorMessage(errorMessage: "Hello")
    }
}


标签: iosswiftios13

解决方案


将视图拖到 tableView 上会创建一个.tableHeaderView. 您可以使用UIContainerView来自另一个视图控制器的视图,但除非您打算进行很多需要以这种方式处理的事情,否则最好使用简单的UIView.

逐步尝试:

1)标准UITableViewController,您的代码准备就绪(将控制器的自定义类分配给TestTableViewController):

在此处输入图像描述

2)添加一个UIView到表视图。给它一个背景颜色,以便于查看:

在此处输入图像描述

3)添加一个UILabel到该视图。给它一个背景颜色,使其易于查看。在所有 4 个方面将其限制为 8 分:

在此处输入图像描述

4)将该视图的自定义类设置为您的ErrorView类:

在此处输入图像描述

5) 连接@IBOutlets。从代码窗口中的圆圈单击并拖动(不是 Ctrl)到对象。您可能会发现拖到大纲窗格中的对象更容易(例如,当您尝试连接视图时,您不会意外连接标签):

在此处输入图像描述

6)现在应该是这样的(代码窗口中的实心圆圈表示插座已连接):

在此处输入图像描述

7)运行应用程序,你应该得到这个:

在此处输入图像描述


推荐阅读