我的Swift程序崩溃与EXC_BAD_INSTRUCTION和以下类似错误之一。这个错误是什么意思,我该如何修复它?

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

or

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


这篇文章旨在收集“意外发现为零”问题的答案,这样它们就不会分散而难以找到。请随意添加您自己的答案或编辑现有的wiki答案。


当前回答

这是一个更重要的注释,这就是为什么隐式打开可选选项在调试nil值时可能具有欺骗性。

考虑下面的代码: 它编译时没有错误/警告:

c1.address.city = c3.address.city

然而在运行时,它给出以下错误:致命错误:在打开可选值时意外地发现nil

你能告诉我哪个对象是nil吗?

你不能!

完整的代码是:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c3 = BadContact()

        c1.address.city = c3.address.city // compiler hides the truth from you and then you sudden get a crash
    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct BadContact {
    var address : Address!
}

struct Address {
    var city : String
}

长话短说,使用var地址:地址!您隐藏了变量可以为nil的可能性,不让其他读取器看到。当它崩溃的时候,你会想“搞什么鬼?!”我的地址不是可选的,所以我为什么要崩溃?!

因此,最好这样写:

c1.address.city = c2.address!.city  // ERROR:  Fatal error: Unexpectedly found nil while unwrapping an Optional value 

你能告诉我哪个对象是nil吗?

这一次,代码对您来说更清楚了。您可以合理地认为,可能是强行打开了address参数。

完整的代码是:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c2 = GoodContact()

        c1.address.city = c2.address!.city
        c1.address.city = c2.address?.city // not compile-able. No deceiving by the compiler
        c1.address.city = c2.address.city // not compile-able. No deceiving by the compiler
        if let city = c2.address?.city {  // safest approach. But that's not what I'm talking about here. 
            c1.address.city = city
        }

    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct GoodContact {
    var address : Address?
}

struct Address {
    var city : String
}

其他回答

如果我的情况下,我设置一个变量UILabel为nil。

所以我修复了它,之后它就没有抛出错误了。

代码片段

class ResultViewController: UIViewController {

    @IBOutlet weak var resultLabel: UILabel!
    var bmiValue=""
    override func viewDidLoad() {
        super.viewDidLoad()
        print(bmiValue)
        resultLabel.text=bmiValue //where bmiValue was nil , I fixed it and problem was solved

    }
    
    @IBAction func recaculateBmi(_ sender: UIButton) {
        self.dismiss(animated: true, completion: nil)
    }
    

}

当我试图从prepareforsegue方法中设置outlet值时,我有过这样的错误:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DestinationVC{

        if let item = sender as? DataItem{
            // This line pops up the error
            destination.nameLabel.text = item.name
        }
    }
}

然后我发现我不能设置目标控制器出口的值,因为控制器还没有加载或初始化。

所以我是这样解决的:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DestinationVC{

        if let item = sender as? DataItem{
            // Created this method in the destination Controller to update its outlets after it's being initialized and loaded
            destination.updateView(itemData:  item)
        }
    }
}

目的地控制器:

// This variable to hold the data received to update the Label text after the VIEW DID LOAD
var name = ""

// Outlets
@IBOutlet weak var nameLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    nameLabel.text = name
}

func updateView(itemDate: ObjectModel) {
    name = itemDate.name
}

我希望这个答案能帮助那些有同样问题的人,因为我发现标记的答案对理解可选选项及其工作方式是很好的资源,但并没有直接解决问题本身。

因为上面的答案清楚地解释了如何安全地玩可选项目。 我将试着解释什么是可选的真正在迅速。

声明可选变量的另一种方法是

在 : 可选<Int>

和可选类型只是一个枚举与两种情况,即

 enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none 
    case some(Wrapped)
    .
    .
    .
}

将nil赋值给变量i。我们可以 var i =可选<Int>.无 或者为了赋值,我们会传递一些值 var i =可选<Int>.some(28)

根据swift, 'nil'是没有值。 为了创建一个用nil初始化的实例,我们必须遵守一个叫做expressiblebynillliteral的协议,如果你猜到了,很好,只有optional符合expressiblebynillliteral,不鼓励符合其他类型。

expressiblebynilleral有一个叫做init(nilleral:)的方法,它用nil初始化实例。你通常不会调用这个方法,根据swift文档,不建议直接调用这个初始化式,因为每当你初始化一个可选类型时,编译器都会调用它,用nil文字。

就连我自己也不得不(没有双关语的意思)把我的脑袋绕在可选科目上:D 快快乐乐。

这是一个更重要的注释,这就是为什么隐式打开可选选项在调试nil值时可能具有欺骗性。

考虑下面的代码: 它编译时没有错误/警告:

c1.address.city = c3.address.city

然而在运行时,它给出以下错误:致命错误:在打开可选值时意外地发现nil

你能告诉我哪个对象是nil吗?

你不能!

完整的代码是:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c3 = BadContact()

        c1.address.city = c3.address.city // compiler hides the truth from you and then you sudden get a crash
    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct BadContact {
    var address : Address!
}

struct Address {
    var city : String
}

长话短说,使用var地址:地址!您隐藏了变量可以为nil的可能性,不让其他读取器看到。当它崩溃的时候,你会想“搞什么鬼?!”我的地址不是可选的,所以我为什么要崩溃?!

因此,最好这样写:

c1.address.city = c2.address!.city  // ERROR:  Fatal error: Unexpectedly found nil while unwrapping an Optional value 

你能告诉我哪个对象是nil吗?

这一次,代码对您来说更清楚了。您可以合理地认为,可能是强行打开了address参数。

完整的代码是:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c2 = GoodContact()

        c1.address.city = c2.address!.city
        c1.address.city = c2.address?.city // not compile-able. No deceiving by the compiler
        c1.address.city = c2.address.city // not compile-able. No deceiving by the compiler
        if let city = c2.address?.city {  // safest approach. But that's not what I'm talking about here. 
            c1.address.city = city
        }

    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct GoodContact {
    var address : Address?
}

struct Address {
    var city : String
}

简单地说 您正在尝试使用可选变量的值为nil。 快速修复可以使用保护或如果让而不是强制打开像放!在变量的末尾