非可选的IBOutlet返回致命错误:从另一个UIViewController类引用时

时间:2018-12-20 15:16:04

标签: swift uiview uiviewcontroller calayer

我在

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

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

在类和标签中还附加了许多约束。

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

所有内容都在情节提要板上连接至正确的插座。在实际的InteractViewController本身中引用它们,我能够调整不透明度,更新图层上的标签等。

但是,除非用户首先使用该应用程序,否则不需要它们。如此简单的InteractViewController上的其他函数调用一个函数来显示和更新这些属性或根本不显示它们。

控制和更新这些属性的函数在另一个类中(项目中的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类InteractViewController:UIViewController上的插座有物理引用?如果是这样,是因为应该以编程方式将它们添加到TipsViewController:UIViewController类(在Xcode中没有物理视觉视图控制器)上吗?

  2. 上的插座有物理参考吗

    InteractViewController类:UIViewController

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

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

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

有人建议我的问题是[What does "fatal error: unexpectedly found nil while unwrapping an Optional value" mean?

的重复项

但这不是我的问题。我的问题专门涉及从另一个ViewController访问一个Outlet,然后再对该Outlet生成一个Nil响应,因为如前所述,InteractViewController显然没有引用ViewController。请阅读Rob提供的解释和答案,Rob会回答此特定问题。

1 个答案:

答案 0 :(得分:0)

您的标题为“从另一个UIViewController类引用时,IBOutlet返回致命错误:”。最重要的是,一个视图控制器绝对不能访问另一个视图控制器的插座。

在代码段中,您使用InteractViewController()语法。不幸的是,这只是实例化视图控制器,而没有在情节提要中连接插座。您需要通过情节提要进行实例化,即使这样,也不能立即引用出口,而只能在稍后调用viewDidLoad之后。无论如何,只有视图控制器本身应该尝试访问其自己的出口。

TipsViewController()InteractViewController()语法表示“创建该视图控制器的新空白实例”。相当于说TipsViewController.init()InteractViewController.init()。而且,更糟糕的是,它根本不使用情节提要(因此不会连接任何插座)。那不是你想要的。您应该避免使用这种ViewController()语法,因为出口将永远无法通过这种方式访问​​。


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

  • 弄清楚是否出示TipsViewController;
  • 如果是,请提供TipsViewController;和
  • 将模型数据(例如,从InteractViewController中检索到的任何UserDefaults传递给为您创建的TipsViewController实例。

但是关于TipsViewController如何呈现其子视图的所有内容,仅是TipsViewController的权限。 InteractViewController切勿直接与TipsViewController的任何渠道互动。