Non optional IBOutlet returns Fatal error: when referenced from another UIViewController class

Non optional IBOutlet returns Fatal error: when referenced from another UIViewController class

我在

中定义了一个 UIView
class InteractViewController: UIViewController {

    @IBOutlet weak var tipsView: UIView!
        var tipslayer: CALayer {
        return tipsView.layer
    }
}

class 中还附加了一些约束以及标签。

@IBOutlet weak var tips1Top: NSLayoutConstraint!
@IBOutlet weak var tips1Right: NSLayoutConstraint!
@IBOutlet weak var tipsTitle: UILabel!
@IBOutlet weak var tipsDesc: UILabel!

所有人都在故事板上连接到正确的出口。在实际的 InteractViewController 本身中引用这些我能够调整不透明度,更新层上的标签等

但是,除非用户第一次使用该应用程序,否则不需要这些,因此在 InteractViewController 上调用一个函数来显示和更新这些属性或根本不显示它们。

控制和更新这些属性的函数在调用的项目中的另一个class(Swift文件中。

class TipsViewController: UIViewController {

    func tips() {
        InteractViewController().tipslayer.transform = CATransform3DMakeScale(0.8, 0.8, 1.0)
    }
}

导致应用崩溃创建

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

return tipsView.layer (the InteractViewController)

tipsView 和 tipslayer 不是可选的,也没有声明为可选的。

我有三个问题希望得到帮助。

  1. 对 ViewController class InteractViewController: UIViewController 上的插座的物理引用是否有问题?如果是这样,是因为它们应该以编程方式添加,而不是在 class TipsViewController: UIViewController(在 Xcode 中没有物理视觉视图控制器) ?

  2. 是否对

    上的网点有物理参考

    class 互动ViewController:UIViewController

如果在 InteractViewController 上调用第二个 ViewContoller 上的函数 TipsViewController.tips() 从未被调用,则创建不必要的内存使用,换句话说,问题 1 的答案基本上是任何物理插座应该以编程方式在 lass 上添加 TipsViewController: UIViewController?

  1. 如果没有内存问题并且知道 tipsView 和返回的 tipslayer 不是可选的,为什么我根本无法从另一个 class 的 tips() 函数中引用它们(TipsViewController: UIViewController)?我看过很多关于 "passing data between view controllers" 的帖子,但我没有在变量或数组之间传递数据。我想/需要简单地更新标签字符串,约束(一个视图控制器class中的对象来自另一个视图控制器class。

我知道人们很忙,所以提前说一下,感谢所有反馈和对问题的帮助。

有人建议我的问题与 [

重复

但这不是我的问题。我的问题具体涉及从另一个 ViewController 访问一个 Outlet,然后生成对 Outlet 的 Nil 响应,因为正如解释的那样,InteractViewController 显然没有引用 ViewController。请阅读 Rob 提供的回答此特定问题的解释和答案。

您的标题是 "IBOutlet returns Fatal error: when referenced from another UIViewController class"。底线是一个视图控制器不应该访问另一个视图控制器的出口。

在您的代码片段中,您使用了 InteractViewController() 语法。不幸的是,这只是实例化视图控制器,但没有连接故事板中的插座。您需要通过故事板进行实例化,即便如此,您也不能立即引用您的 outlet,只能在稍后调用 viewDidLoad 之后。无论如何,只有视图控制器本身应该尝试访问它自己的插座。

TipsViewController()InteractViewController() 语法表示 "create a new, blank instance of that view controller"。这相当于说 TipsViewController.init()InteractViewController.init()。而且,更糟糕的是,它根本没有使用故事板(因此不会连接任何插座)。那不是你想要的。您应该避免使用这种 ViewController() 语法,因为这样就永远无法访问出口。


InteractViewController 应确定是否应显示 TipsViewController(例如检查用户默认值),如果是,则显示它。但是,InteractViewController 唯一应该做的是:

  • 判断是否要呈现TipsViewController;
  • 如果是,请提出 TipsViewController;和
  • 将模型数据(例如 InteractViewControllerUserDefaults 检索到的任何内容)传递给为您创建的 TipsViewController 实例。

但是关于 TipsViewController 如何呈现其子视图的任何事情,都是 TipsViewController 的权限。 InteractViewController 不应直接与 TipsViewController 的任何媒体互动。