Swift-不断收到“致命错误:在展开可选值时意外发现 nil”

Posted

技术标签:

【中文标题】Swift-不断收到“致命错误:在展开可选值时意外发现 nil”【英文标题】:Swift-Keep getting "fatal error: unexpectedly found nil while unwrapping an Optional value" 【发布时间】:2015-07-08 06:28:34 【问题描述】:

我只使用 Swift 和 Xcode 6 几个星期,但我已经在构思一个应用程序的想法。我正在尝试处理的应用程序部分将如下所示: 1) 用户有一个按钮网格,每个按钮在点击时执行不同的操作 2) 用户可以点击视图右下角的齿轮按钮,然后会以模态方式呈现新视图,即临时设置窗格(标签和开关)。如果按钮名称标签的开关关闭,则该按钮被隐藏。 3)用户点击一个保存按钮(目前与 NSUserDefaults 无关,也与关闭应用程序后实际保存功能无关,它目前实际上只是一个后退按钮)并且任何关闭的开关都会使其各自的按钮出口隐藏。

然而,实际的项目是这样运行的: 1) 完美运行 2)当我点击齿轮时,设置窗格按计划出现。我也可以左右滑动开关,但是当我点击保存按钮时,应用程序崩溃并且我在控制台中收到“致命错误:在展开可选值 (lldb) 时意外发现 nil”。

这是我的代码:

这是第一个带有按钮的视图控制器的一部分:

@IBAction func soundButton(sender: AnyObject) 
    var soundID: SystemSoundID = 0
    let soundFile: String = NSBundle.mainBundle().pathForResource("Sound", ofType: "wav")!
    let soundURL: NSURL = NSURL(fileURLWithPath: soundFile)!
    AudioservicesCreateSystemSoundID(soundURL, &soundID)
    AudioServicesPlaySystemSound(soundID)

以上是按下按钮时播放声音的动作。

现在这里是按钮的出口和边框的出口:

 @IBOutlet var soundOutlet: UIButton!
 @IBOutlet var soundRingOutlet: UIImageView!

在故事板中,我有一个标签栏控制器和两个视图(ViewController 和 ViewControllerTwo),为了访问设置视图(SettingsViewController),我在右下角制作了一个带有齿轮图像的按钮,它通过模态呈现的 segue 连接到设置窗格。这是 SettingsViewController 的部分代码:

//The switch
@IBOutlet var soundSwitch: UISwitch!

问题出在哪里:

@IBAction func saveButton(sender: AnyObject)  if soundSwitch.on
    (presentedViewController as! ViewController).soundOutlet.hidden = true else (presentedViewController as! ViewController).soundOutlet.hidden = false
    dismissViewControllerAnimated(true, completion: nil)
    

问题是从“presentedViewController”的第二个实例变为“false” 非常令人沮丧的问题,我已经为此工作了几个小时,交换了代码,研究了这个,但似乎没有任何效果。显然我缺少一些东西,毕竟这只是在视图之间交换数据。

更新:我已将问题中的两个“presentedViewController”改为“presentingViewController”。我在控制台中收到此错误消息:“无法将 'Buttons.TabBarViewController' (0x10d590d90) 类型的值转换为 'Buttons.ViewController' (0x10d590e10)。 (lldb)" “Buttons”是项目名称。

【问题讨论】:

不就是presentedViewController是nil吗? 你正在升级你的 VC:presentedViewController as! ViewController。丢失其中的属性(包括soundOutlet)。 @Ichamp 有没有其他方法可以从我的应用程序的另一个视图访问代码而无需向上转换? 详细解释请参考以下链接。重复问题。 ***.com/a/32170457/6602495 【参考方案1】:

presentingViewController 是您的 tabBarViewController,而 presentedViewController 是您所期望的正在呈现的 ViewController,但实际上这个变量是 nil 因为在在您单击此按钮的时间点,模态视图控制器由于某种原因没有设置 presentViewController 变量,因此该变量实际上是 nil,当您尝试在 nil 变量上使用 as! ViewController 时,您正试图将 nil 转换为不可能这样你就崩溃了,你必须找到其他方法来获取将要呈现的视图控制器

【讨论】:

我得到了 '@IBAction func saveButton(sender: AnyObject) if soundSwitch.on ViewController.soundOutlet.hidden = true else ViewController.soundOutlet.hidden = false dismissViewControllerAnimated(true, completion: nil ) ' 但我得到一个 Swift 编译器错误:“'ViewController.Type' 没有名为 'soundOutlet' 的成员”我错过了什么吗? ViewController 是类的名称,因此您尝试以这种方式访问​​静态成员(它没有),尝试使用 presentingViewController.soundOutlet 我想我现在看到了问题,我改变了我的答案 在故事板中,视图呈现的顺序为:TabBarController->(两个选项卡式 ViewControllers)ViewController 和 ViewControllerTwo->SettingsViewController。现在,我们讨论的所有这些代码都在 SettingsViewController 中,而不是 ViewController,这会改变什么吗? 啊,是的,这就是为什么presentViewController 为nil,我假设这是来自TabBarController,您可能需要将TabBarController 的引用传递给设置页面,以便您可以访问ViewController,或者只是 ViewController 本身(你可能应该更好地命名你的类,与这些平淡无奇的名称混淆:P)【参考方案2】:

红色,大部分看起来都还可以。只是一些提示。

    您不必重复变量声明。

    让 soundURL: NSURL = NSURL(fileURLWithPath: soundFile)!

在这种情况下,Swift 会通过你的赋值来推断你的类型。

    正如其他人所提到的,为您的控制器使用描述性的类名称。当您试图弄清楚课程的目的时,它将为您节省大量时间。我们都去过那里 8>)。

您需要实例化一个包含 soundOutlet 属性的控制器实例。比如:

let dvc = YourControllerClass() 
dvc.soundOutlet.hidden = true
dvc.modalTransitionStyle = UIModalTransitionStyle.FlipHorizontal
dvc.modalPresentationStyle = UIModalPresentationStyle.Popover
dvc.presentViewController(YourViewController, animated: true, completion: nil)

如果您还没有弄清楚,请发布更多您的实现。

祝你好运。

【讨论】:

感谢您的详细解答。这是给 SettingsViewController 的,对吧?因为我已经在 vc 的一部分中更新了“if”语句以读取:@IBAction func saveButton(sender: AnyObject) if soundSwitch.on let dvc = ViewController() dvc.soundOutlet.hidden = true else let dvc = ViewController() dvc .soundOutlet.hidden = falsedismissViewControllerAnimated(true, completion: nil) 不幸的是,我仍然得到同样的 nil 展开错误。 我也不需要关闭或展开 SettingsViewController,而不是通过 segue 呈现 ViewController(我一直听说这样的 segue 循环会占用大量 RAM)?

以上是关于Swift-不断收到“致命错误:在展开可选值时意外发现 nil”的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

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

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

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