在展开可选值时发现 nil

Posted

技术标签:

【中文标题】在展开可选值时发现 nil【英文标题】:Found nil while unwrapping optional value 【发布时间】:2015-12-01 18:07:01 【问题描述】:

您可能会想:“关于此错误的另一篇文章”。 是的,在写这个问题之前我一直在研究这个论坛,不幸的是我找不到可以帮助的东西,或者至少我知道当有一个未绑定的 var 时这个错误就会出现。

但是,由于我对此很陌生,因此我需要一些帮助。 我正在按照指南制作一个简单的无限横向卷轴游戏。 到目前为止一切顺利,但后来我遇到了这个“nill”错误。 指南本身没有这个错误。

所以我认为可能是我使用了更新版本的 xCode 或 iphone 模拟。但我很确定不是那个。

到目前为止我的编码:

import Foundation

class MainScene: CCNode 
    weak var hero: CCSprite!

    func didLoadFromCCB() 
       userInteractionEnabled = true
    

    override func touchesBegan(touch: CCTouch!, withEvent event: CCTouchEvent!) 
       // This is the error line. I think it is caused by (applyImpulse(ccp(0, 400)) )
        hero.physicsBody.applyImpulse(ccp(0, 400)) 
    

我怎样才能简单地解决这个问题? 我应该用 applyImpulse 做一个变量吗? 我也试过在CGPoint(ccp)和CCPackage之间切换,都没有用。

【问题讨论】:

【参考方案1】:
  weak var hero: CCSprite!

这是非常危险的,很可能是您的问题的原因。除了使用几乎总是要避免的! 之外,它还与weak 混合使用。这意味着如果 something else 停止指向 herothis 变量将成为隐式展开的 nil。下次访问它时,您会崩溃。

首先,去掉!。如果需要weak,请使用?。除此之外,决定它是否真的很强大。您在此处显示的任何内容都表明它应该很弱。

【讨论】:

您好,非常感谢您的反应。我试图改变“!”变成一个“?”。它告诉我它没有被包装。然后我尝试切换每个!变成一个?它只是给了我同样的错误。是的,根据本教程,它确实需要是一个弱变量。 “在代码中完成代码连接时,我们将始终使用格式 weak var codeConnectionName: Type!。等你有更多 Swift 经验后,我们会解释这意味着什么。” 您的教程可能正在讨论 IBOutlets(这可能是“连接”的意思)。我无法想象有任何理由在非 IBOutlet 上同时使用 weak!。这不是 IBOutlet,也没有连接到故事板或 XIB。 (我不知道你在这里所说的“它没有被包装”是什么意思。我怀疑你不熟悉可选项的工作原理?) 包装部分,是 xCode 给我的错误。我也不太擅长编码,因为我还是个初学者。我确实遵循了一些解释选项如何工作的指南,我只需要习惯它。【参考方案2】:

我认为上面的错误代码会给新手造成很大的困惑,因为我们不知道 swift 2.0 和旧版本的 swift 中什么是“可选”的。例如,我遇到了同样的错误,无法判断问题出在哪里。我发现我正在使用括号 () 调用一个方法,并且在同一个函数中我调用了没有括号的方法。这导致了上面的错误。 () 是一个可选组件,按照我的理解,它在 Swift 2.0 中成为可选组件。调用方法时必须保持一致,否则编译器将抛出“在展开可选值时发现 nil 错误”。这是我的代码:我调用不一致的方法是 NSDirectoryEnnumerationOptions()。这在我分享的示例中得到了纠正:

      func listFilesWithFilter() -> [String]

NSFileManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
    let musicUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
    do
        let fileList = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(musicUrl,includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions())
        print(fileList)
     catch let error as NSError 
        print(error.localizedDescription)
    
    // filter for wav files 
    do 
        let directoryUrls = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(musicUrl, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions())
        print(directoryUrls)
        let wavFiles = directoryUrls.filter() $0.pathExtension == "wav".map $0.lastPathComponent
        print ("WavFiles:\n" + wavFiles.description)
     catch let error as NSError 
        print(error.localizedDescription)
    
    return wavFiles
      

【讨论】:

感谢您的额外指导。但是,您给出的示例使我感到困惑。您是否在此示例中错误地调用了 NSDirectoryEnnumerationOptions() 并进行了更正?当它是一个糟糕的代码时它是什么样子的? 我对 NSDirectoryEnumerationOptions() 进行了两次调用,一次带有括号,另一次没有括号,这导致了错误。所以第二个调用是 NSDirectoryEnumerationOptions。这是错误与可选组件相关的地方。关键是,只要您保持一致,这两种选择都是可以接受的。希望这有助于澄清任何困惑。 所以我正在查看我的代码,一切都只是“好”。但是,我认为 nil 问题是由 weak var hero: CCSprite! 引起的,正如 Rob Napier 之前所说。我知道变量必须是数字,但本教程给了我这个?

以上是关于在展开可选值时发现 nil的主要内容,如果未能解决你的问题,请参考以下文章

Alamofire:在展开可选值时意外发现 nil

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

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

Alamofire 平面错误:在展开可选值时意外发现 nil

prepareForSegue 出错“”在展开可选值时意外发现 nil“”

在展开可选值时迅速并意外发现 nil