【问题标题】:Swift Delegation: unexpectedly found nil while unwrapping an Optional valueSwift 委派:在展开 Optional 值时意外发现 nil
【发布时间】:2017-07-06 13:50:02
【问题描述】:

编辑:请注意以下问题讨论在之间使用委托 在 UITabBarController 中实现的 2 个视图控制器。

我在这里和 YouTube 上进行了相当多的搜索,但没有看到我的问题在其他地方被复制。我会保持重点。

我有 2 个我自己编写的视图控制器——不是由 XCode 生成的——; TabOneController 和 TabTwoController

以下是两者的编码...

import UIKit

class TabOneController: UIViewController{


    private let instanceOfTabOneView = TabOneView()

    var vc1Delegate: fromOneToTwo!

    override func loadView() {

        super.loadView()

            view.addSubview(instanceOfTabOneView.buildTheVu())
                view.backgroundColor = UIColor.white

        runThisOnce()

        }

    func runThisOnce(){

        vc1Delegate.passTheValue(heroNameIs: "pass this to TabTwoController")

    }

}

protocol fromOneToTwo{

    func passTheValue(heroNameIs: String)

}

至于标签 2...

import UIKit

class TabTwoController: UIViewController, fromOneToTwo{


    private let instanceOfTabTwoView = TabTwoView()


    override func loadView() {

        super.loadView()

            view.addSubview(instanceOfTabTwoView.buildTheVu())

        assignDelegateToSelf()

    }

    func assignDelegateToSelf(){

        let instanceTabOne = TabOneController()
            instanceTabOne.vc1Delegate = self

    }

    func passTheValue(heroNameIs:String){

        instanceOfTabTwoView.txtFld.text = heroNameIs

    }

}

我在运行时遇到以下错误-应用构建成功-...

致命错误:在展开可选值时意外发现 nil

在下一行...

vc1Delegate.passTheValue(heroNameIs: "pass this to TabTwoController")

当我注释掉上面的行时,应用程序构建并运行成功,但应用程序当然不执行委托。

我有点理解编译器试图告诉我的意思,即

vc1Delegate

还没有被实例化-我猜-。但是我在每块岩石下都搜索过,似乎找不到解决方法。

如果有任何帮助或指导,我将不胜感激。抱歉,如果我的代码看起来不成熟,我是 Swift 和一般编程的新手。谢谢。

【问题讨论】:

    标签: swift3 delegates runtime-error optional


    【解决方案1】:

    UITabBarController 中,默认情况下第一个选项卡正在实例化。视图控制器初始化执行loadView并找到nil,因为第二个选项卡还没有初始化;这是正常行为。我的建议是使用 ? 后缀使代理弱可选,并在其他地方运行代理代码。此外,请始终将类和协议名称中的第一个字母大写。

    weak var vc1Delegate: FromOneToTwo?
    

    如果此结构是强制性的,请尝试使用自定义通知观察器。

    【讨论】:

    • 感谢您的回复。我将创建一个带有 2 个常规 Viewcontroller 的 Xcode 项目,并用变量替换任何 UI 控件。如果 UITabController 是问题,我会发表另一条评论。感谢您的宝贵时间。
    【解决方案2】:

    首先,您的错误发生在var vc1Delegate: fromOneToTwo! 行,而您将此委托变量声明为非空,然后在其上调用passTheValue。正确的做法是

    var vc1Delegate: fromOneToTwo?
    
    func runThisOnce(){
        if let delegate = vc1Delegate {
            vc1Delegate.passTheValue(heroNameIs: "pass this to TabTwoController")
        }
    }
    

    其次,您没有正确使用委托。在assignDelegateToSelf() 函数中,您正在创建TabOneController 的新实例 然后分配委托。相反,您需要找出现有的TabOneController 实例并分配委托。

    【讨论】:

    • 如何找到现有的TabOneController 实例?
    • @Sebastian 这取决于您的代码是如何编写的...如果您想要委托调用,您必须为控制器注册委托,然后您只能接收来自该控制器的委托调用。通常,如果您对新的视图控制器使用故事板和正常的 segue,则无需关心这一点,因为您将只有一个视图控制器实例。但是,当您以编程方式创建视图控制器时(例如从情节提要函数调用 initialed),您只需启动一次并将该瞬间存储在某处,以便您以后可以找到它并接收调用。
    • 感谢您的解释。我可以通过在触发 segue 时将当前 viewcontroller 类保存在一个变量中,然后在 segue 期间将该变量传递给另一个视图控制器来做到这一点
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 2019-09-23
    • 1970-01-01
    相关资源
    最近更新 更多