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

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

or

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


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


当前回答

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

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

在 : 可选<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 快快乐乐。

其他回答

This is because you are trying to use a value which can possible be nil, but you decided you don't want to have to check it, but instead assume its set when you uses it and define it as !, there are different philosophies on use of variable set as force unwrap, some people are against there use at all, I personal think they are ok for things that will crash all the time and are simple to reason about, usually references to resource, like outlets to xib files, or uses of images with you app that are part of your assets, if these are not set up properly, you app is going to crash straight away, for a very obvious reason, you can get into difficult when the order of objects being created can be uncertain, and trying to reason solutions to this can be difficult, it usually means a bad design as even it you make them optional, calls to you optional variable may not ever be executed, some projects can demand use of force unwraps for security reasons, things like banking apps, because they want the app to crash rather then continue to work in an unplanned way.

这是一个更重要的注释,这就是为什么隐式打开可选选项在调试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
}

我在从表视图控制器到视图控制器进行segue时遇到了这个错误,因为我忘记在主故事板中为视图控制器指定自定义类名。

一些简单的东西值得检查,如果其他看起来都没问题

TL;博士回答

除了极少数例外,这条规则是黄金法则:

避免使用!

声明变量是可选的(?),而不是隐式地打开可选的(IUO) (!)

换句话说,应该使用: var nameOfDaughter:字符串?

而不是: var nameOfDaughter:字符串!

使用if let或guard let展开可选变量

要么像这样展开变量:

if let nameOfDaughter = nameOfDaughter {
    print("My daughters name is: \(nameOfDaughter)")
}

或者像这样:

guard let nameOfDaughter = nameOfDaughter else { return }
print("My daughters name is: \(nameOfDaughter)")

这个答案是简洁的,为了充分理解阅读接受的答案


资源

避免强制展开

错误EXC_BAD_INSTRUCTION和致命错误:在隐式地展开Optional值时意外地发现nil,在声明@IBOutlet但没有连接到故事板时出现的最多。

你还应该了解其他答案中提到的可选选项是如何工作的,但这是唯一一次出现在我身上。