斯威夫特3 - 准备癫痫

时间:2016-11-08 01:55:35

标签: ios swift swift3

我的故事板中有3个场景。我的初始View Controller是一个导航控制器,然后有一个关系根视图控制器到UI ViewController(视图控制器a),然后我有一个从ViewController中的按钮到第三个ViewController(视图控制器b)的推送segue现场。我给push segue一个标识符。现在我正在尝试在第二个视图控制器(视图控制器a)中准备我的segue,如下所示:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "HistorySegue" {
            if let viewController = segue.destination as? HistoryController {
                viewController.detailItem = barcodeInt as AnyObject
            }
        }
    }

然而,当我运行此代码并按下控制器中的按钮时,我收到以下错误:

致命错误:尝试桥接包含nil

的隐式展开的可选项

我做错了什么?

3 个答案:

答案 0 :(得分:6)

用以下内容替换您的代码,它至少不会崩溃。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "HistorySegue" {
            if let viewController = segue.destination as? HistoryController {
              if(barcodeInt != nil){
                viewController.detailItem = barcodeInt as AnyObject
               }
            }
        }
    }

答案 1 :(得分:1)

必须将barcodeInt定义为隐式解包的可选项,例如:

var barcodeInt:Int!

在这种情况下,如果在将其分配给detailItem时为nil,则由于!,swift会认为它存在非零值且取消引用它。那是一个运行时错误。最好的办法是避免在你编写的代码中!(例如,可以保留Apple生成的IBOutlets代码),如果可能的话,在返回隐式解包的选项之前了解有关选项的更多信息。然后,仍然谨慎使用它们。

更适合您情况的代码:

if let viewController = segue.destination as? HistoryController, 
   let barcodeInt = barcodeInt as? AnyObject {

   viewController.detailItem = barcodeInt
} else {
   NSLog("Error: expected barcodeInt to be set") 
}

答案 2 :(得分:0)

我有同样的问题。逻辑是先准备序列(加载容器视图引用的UIViewController),将其分配给变量,然后在viewDidLoad()中使用它。该代码应该可以工作:

Swift 4.2

// usually an IBoutlet
var viewController: HistoryController!

override func viewDidLoad() {
    super.viewDidLoad()

    viewController.detailItem = barcodeInt as AnyObject
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "HistorySegue"
    { viewController = segue.destination as! HistoryController }
}

detailItem可以在HistoryController中定义为IBoutlet,它取决于OP代码。就我而言,我有两个简单的容器视图,每个视图内部都有一个标签,这是主视图控制器类的最终工作代码:

import UIKit

class ViewController: UIViewController {

    @IBOutlet var firstView: ReusableViewController!
    @IBOutlet var secondView: ReusableViewController!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        firstView.myLabel.text = "My 1st reuse!!!"
        secondView.myLabel.text = "And that's the 2nd!"
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "segueFirstView")
        { firstView = (segue.destination as! ReusableViewController) }
        if (segue.identifier == "segueSecondView")
        { secondView = (segue.destination as! ReusableViewController) }
    }
}

最终,我可以直接从主控制器更改两个不同的UILabel的文本!

要详细了解如何使用容器视图,请检查this S.O. answer