Ios 对新手的快速帮助

Ios 对新手的快速帮助,ios,swift,Ios,Swift,我收到以下错误消息,无法找出我做错了什么。这是我的第一个程序,不知道如何调试它 错误消息: 致命错误:在展开可选值时意外发现nil (lldb) 代码: 在使用前,需要检查filePathUrl的值是否为非零 NSURL.fileURLWithPath(filePath)返回一个可选值,该值可能为零。使用前应检查: if let filePath = NSBundle.mainBundle().pathForResource("crankringtone", ofType: "mp3"){

我收到以下错误消息,无法找出我做错了什么。这是我的第一个程序,不知道如何调试它

错误消息:

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

代码:


在使用前,需要检查
filePathUrl
的值是否为非零

NSURL.fileURLWithPath(filePath)
返回一个可选值,该值可能为零。使用前应检查:

if let filePath = NSBundle.mainBundle().pathForResource("crankringtone", ofType: "mp3"){
    if let filePathUrl = NSURL.fileURLWithPath(filePath) {
        audioPlayer = AVAudioPlayer(contentsOfURL: filePathUrl, error: nil)
    }
} else {
    println("file path is empty")
}

在代码中,您已经声明了变量audioPlayer
var audioPlayer:AVAudioPlayer感叹号表示展开时不能为零

因此,在该代码中:

if var filePath = NSBundle.mainBundle().pathForResource("crankringtone", ofType: "mp3"){
    var filePathUrl = NSURL.fileURLWithPath(filePath)

    audioPlayer = AVAudioPlayer(contentsOfURL: filePathUrl, error: nil)
} else {
   println("file path is empty")
}
您有一个名为
filePathUrl
的变量。该变量使用的是
NSURL.fileURLWithPath(filePath)
。这可以返回
nil
。如果是,则变量
filePathUrl
为零。然后当您在
audioPlayer
中使用它时,它是nil,因此
audioPlayer
返回nil

但是请记住,
audioPlayer
有一个
。不可能是零。因此,您可以做的(最简单的选择)是使用一个额外的if语句:

if let filePath = NSBundle.mainBundle().pathForResource("crankringtone", ofType: "mp3"){
   if let filePathUrl = NSURL.fileURLWithPath(filePath) {
       audioPlayer = AVAudioPlayer(contentsOfURL: filePathUrl, error: nil)
   }
} else {
   println("file path is empty")
}

这个额外的if语句双重检查
filePathUrl
是否为空。如果是,则将程序发送到else语句。如果它不是nil,那么它允许
audioPlayer
执行它的操作。而且,因为我们知道该值不是零,audioPlayer不会返回错误。

当您点击按钮并调用
playSlowAudio
函数时,很可能会发生崩溃

问题是您正在为
audioPlayer
使用隐式展开的可选选项。如果播放机初始化失败(例如,找不到文件),则
audioPlayer
将为
nil
。因此,当调用按钮操作时,
audioPlayer.stop()
在调用
stop()
之前尝试打开
audioPlayer
,这会导致崩溃

要修复此问题,请将
audioPlayer
更改为常规选装配置:

var audioPlayer:AVAudioPlayer?

并与更安全的可选链接一起使用:

audioPlayer?.stop()

因此,完整示例如下所示:


import UIKit
import AVFoundation

class PlaySoundsViewController: UIViewController {
    var audioPlayer:AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        if var filePath = NSBundle.mainBundle().pathForResource("crankringtone", ofType: "mp3"){
            var filePathUrl = NSURL.fileURLWithPath(filePath)

            audioPlayer = AVAudioPlayer(contentsOfURL: filePathUrl, error: nil)
        } else {
            println("file path is empty")
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func playSlowAudio(sender: UIButton) {
        audioPlayer?.stop()
    }
}

如果var…
是合法的,但是在大多数情况下,
如果let…
是更好的选择cases@bolot我从未在官方文件中看到过
如果变量…
。我不知道这是合法的。无论如何,这绝对不是最佳实践。从苹果在Swift上的文档:“您可以将常量和变量与可选绑定一起使用。如果您想在If语句的第一个分支中操作actualNumber的值,可以改为写入If var actualNumber,并且optional中包含的值将作为变量而不是常量提供。“@vacawama谢谢你的推荐。我猜我只是犯了一个粗心的错误。@Sw在哪一行出现了
致命错误:在解包可选值(lldb)时意外地发现了nil
发生了?我之前在那里有一个错误的mp3文件名-这就是问题所在吗?您仍然遇到崩溃吗?或者它只是不起作用?没有崩溃。它只是不起作用。我把println的一切都搞定了,并确认音频播放器没有被创建。

import UIKit
import AVFoundation

class PlaySoundsViewController: UIViewController {
    var audioPlayer:AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        if var filePath = NSBundle.mainBundle().pathForResource("crankringtone", ofType: "mp3"){
            var filePathUrl = NSURL.fileURLWithPath(filePath)

            audioPlayer = AVAudioPlayer(contentsOfURL: filePathUrl, error: nil)
        } else {
            println("file path is empty")
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func playSlowAudio(sender: UIButton) {
        audioPlayer?.stop()
    }
}