【问题标题】:How do you fix the "found nil while unwrapping optional value" error when trying to play sound?尝试播放声音时如何解决“在展开可选值时发现 nil”错误?
【发布时间】:2020-07-17 00:48:41
【问题描述】:

我正在制作一个播放声音的函数

func playSound(soundName: String) {
    let url = Bundle.main.url(forResource: soundName, withExtension: "wav")
    player = try! AVAudioPlayer(contentsOf: url!)
    player.play()
}

然后在包含我所有按钮的 IBAction 中调用此函数

@IBAction func buttonPiano(_ sender: UIButton) {
    playSound(soundName: String(sender.currentTitle!))
    
    sender.backgroundColor = UIColor.white
    sender.alpha = 0.3
    
    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300), execute: {
        sender.backgroundColor = UIColor.systemBackground
        sender.alpha = 1
    })       
}

运行我能做的应用程序。但是每当你按下一个按钮时,它就会崩溃并给我这个错误:

致命错误:在展开可选值时意外发现 nil:文件 /Users/administrator/Desktop/Xcode Projects/pianoButtons/pianoButtons/ViewController.swift,第 37 行

可选值好像是url!来自我的声音功能。

我已经尽我所能,但没有运气。如何避免此错误并在不崩溃的情况下播放声音?

【问题讨论】:

  • 您确定soundName.wav 文件存在吗?检查soundName 是什么并检查该文件是否存在。另外,与问题无关但也很重要,you are using AVAudioPlayer wrongly
  • soundName 是一个变量,它获取按下按钮的标题,然后使用该标题查找声音文件(例如,按下 C 按钮应该播放 C.wav)。
  • 什么是ViewController.swift, line 37
  • 设置断点,一步一步看nil出现的时候。简单、猜测少、学习曲线最长。
  • 当发件人不是 UIButton 或没有标题时,波形文件名将以 nil 结尾。虽然接管可能的按钮看起来很容易 currentTitle 它更安全地询问发件人是否是 UIButton 类以及如果标题为 nil 该怎么办。

标签: swift xcode audio null optional


【解决方案1】:

确保您的 soundName.wave 文件显示在复制包资源中。您可以通过单击您的项目 > 选择您的目标 > 构建阶段 > 复制捆绑资源来找到它。如果您在那里没有看到它,请单击加号按钮添加它。

var soundPlayer: AVAudioPlayer?
 func playSentSound() {
    DispatchQueue.main.async{
        let path = Bundle.main.path(forResource: "soundName.mp3", ofType: nil)!
        let url = URL(fileURLWithPath: path)

        do {
            self.soundPlayer = try AVAudioPlayer(contentsOf: url)
            print("Playing")
            self.soundPlayer?.play()
        } catch {
            // couldn't load file :(
            print("Cant Load File")
        }
    }
}

【讨论】:

    【解决方案2】:

    您的代码实际上是在调用它

    try! AVAudioPlayer(contentsOf: Bundle.main.url(forResource: String(button.currentTitle!), withExtension: "wav")!)
    

    每个! 都是潜在的崩溃。这是它们会发生的时候

    1. 按钮在触发操作时可能没有当前标题。
    2. 主包可能没有具有该名称/扩展名的资源
    3. 音频播放器可能无法播放该文件的内容

    在您的特定情况下,它似乎在 2 处失败。处理此问题的更好方法是这样

    if let url = Bundle.main.url(forResource: soundName, withExtension: "wav") {
      player = try! AVAudioPlayer(contentsOf: url)
    } else {
      print("No resouce named \(soundName).wav")
    }
    

    首先,您的应用不会播放声音而是崩溃,其次您会收到一条有用的日志消息,该消息可能会告诉您为什么找不到资源。

    理想情况下,您的所有! 都应替换为类似的结构,以记录错误或执行一些后备操作而不是崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多