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

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

or

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


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


当前回答

首先,您应该知道什么是Optional值。 详细信息请参见《Swift编程语言》。

其次,您应该知道可选值有两个状态。一个是全值,另一个是空值。因此,在实现一个可选值之前,应该检查它是哪个状态。

你可以用if let…或者守卫让…Else等等。

还有一种方法,如果你不想在实现之前检查变量的状态,你也可以使用var buildingName = buildingName ??“buildingName”。

其他回答

如果我的情况下,我设置一个变量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 快快乐乐。

基本上,你试图在Swift只允许非nil值的地方使用nil值,通过告诉编译器信任你,那里永远不会有nil值,从而允许你的应用程序编译。

有几种情况会导致这种致命错误:

forced unwraps: let user = someVariable! If someVariable is nil, then you'll get a crash. By doing a force unwrap you moved the nil check responsibility from the compiler to you, basically by doing a forced unwrap you're guaranteeing to the compiler that you'll never have nil values there. And guess what it happens if somehow a nil value ends in in someVariable? Solution? Use optional binding (aka if-let), do the variable processing there: if user = someVariable { // do your stuff } forced (down)casts: let myRectangle = someShape as! Rectangle Here by force casting you tell the compiler to no longer worry, as you'll always have a Rectangle instance there. And as long as that holds, you don't have to worry. The problems start when you or your colleagues from the project start circulating non-rectangle values. Solution? Use optional binding (aka if-let), do the variable processing there: if let myRectangle = someShape as? Rectangle { // yay, I have a rectangle } Implicitly unwrapped optionals. Let's assume you have the following class definition: class User { var name: String! init() { name = "(unnamed)" } func nicerName() { return "Mr/Ms " + name } } Now, if no-one messes up with the name property by setting it to nil, then it works as expected, however if User is initialized from a JSON that lacks the name key, then you get the fatal error when trying to use the property. Solution? Don't use them :) Unless you're 102% sure that the property will always have a non-nil value by the time it needs to be used. In most cases converting to an optional or non-optional will work. Making it non-optional will also result in the compiler helping you by telling the code paths you missed giving a value to that property Unconnected, or not yet connected, outlets. This is a particular case of scenario #3. Basically you have some XIB-loaded class that you want to use. class SignInViewController: UIViewController { @IBOutlet var emailTextField: UITextField! } Now if you missed connecting the outlet from the XIB editor, then the app will crash as soon as you'll want to use the outlet. Solution? Make sure all outlets are connected. Or use the ? operator on them: emailTextField?.text = "my@email.com". Or declare the outlet as optional, though in this case the compiler will force you to unwrap it all over the code. Values coming from Objective-C, and that don't have nullability annotations. Let's assume we have the following Objective-C class: @interface MyUser: NSObject @property NSString *name; @end Now if no nullability annotations are specified (either explicitly or via NS_ASSUME_NONNULL_BEGIN/NS_ASSUME_NONNULL_END), then the name property will be imported in Swift as String! (an IUO - implicitly unwrapped optional). As soon as some swift code will want to use the value, it will crash if name is nil. Solution? Add nullability annotations to your Objective-C code. Beware though, the Objective-C compiler is a little bit permissive when it comes to nullability, you might end up with nil values, even if you explicitly marked them as nonnull.

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

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