Swift:AVAudioPlayer无法播放,线程可能出错?

时间:2019-05-09 17:20:49

标签: ios swift xcode audio avaudioplayer

我目前正在开发一个基于图像/对象状态播放音频剪辑的应用。

当前我收到此错误代码。

线程1:EXC_BAD_ACCESS(代码= 1,地址= 0x48)

我想如果已经在同一线程上播放了另一个音频剪辑,则尝试在同一线程上播放另一个音频剪辑可能会出错。

但是说实话,我不确定,我仍在学习有关线程和多线程的知识,所以我很可能到达这里。

我在这里想念什么?我如何才能播放第二个音频剪辑(turnSaberOffAudio),而不会收到此错误消息?谢谢!

这是我点击按钮时发生的情况。

@objc func lightsaberTapped() {
    print("lightsaber open!")

    if lightsaberModel.isSaberOn == false {
        UIView.animate(withDuration: 0.2, animations: {
            self.saberImageHeightConstraint.constant = 530
            self.saberImageWidthConstraint.constant = 210
            self.mainView.layoutIfNeeded()
            self.viewDidLayoutSubviews()
        }, completion: nil)
        lightsaberModel.turnSaberOnAudio.play()
        lightsaberModel.isSaberOn = true
    } else {
        UIView.animate(withDuration: 0.2, animations: {
            self.saberImageHeightConstraint.constant = 1
            self.saberImageWidthConstraint.constant = 1
            self.mainView.layoutIfNeeded()
            self.viewDidLayoutSubviews()
        }, completion: nil)
        lightsaberModel.turnSaberOffAudio.play()
        lightsaberModel.isSaberOn = false
    }
}

这是带有必要信息的模型。

class Model {

    var turnSaberOnAudio: AVAudioPlayer = AVAudioPlayer()
    var turnSaberOffAudio: AVAudioPlayer = AVAudioPlayer()
    var whichLightsaber = String()
    var isSaberOn = Bool()

    func turnSaberOn() {
        let turnSaberOnPath = Bundle.main.path(forResource: "SaberOn", ofType: "wav")
        do {
            turnSaberOnAudio = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: turnSaberOnPath!))
        }
        catch {
            print(error)
        }
    }

    func turnSaberOff() {
        let turnSaberOffPath = Bundle.main.path(forResource: "SaberOff", ofType: "mp3")
        do {
            turnSaberOffAudio = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: turnSaberOffPath!))
        }
        catch {
            print(error)
        }
    }
}

1 个答案:

答案 0 :(得分:0)

这是你永远不应该做的事情:

var turnSaberOnAudio: AVAudioPlayer = AVAudioPlayer()

空的初始化程序AVAudioPlayer()会产生一些无用的东西,这不仅是无用的,而且还会导致崩溃。

并且将var声明为非可选,则无法区分它是否包含有用的内容。


使用您当前的代码,调用turnSaberOn()时可能不会调用turnSaberOff()play()

尝试将您的Model更改为:

class Model {

    var turnSaberOnAudio: AVAudioPlayer? //<- Never use `AVAudioPlayer()`
    var turnSaberOffAudio: AVAudioPlayer? //<- Never use `AVAudioPlayer()`
    var whichLightsaber: String = ""
    var isSaberOn: Bool = false

    init() {
        let turnSaberOnUrl = Bundle.main.url(forResource: "SaberOn", withExtension: "wav")!
        do {
            turnSaberOnAudio = try AVAudioPlayer(contentsOf: turnSaberOnUrl)
            turnSaberOnAudio!.prepareToPlay()
            print("\(turnSaberOnUrl) loaded")
        } catch {
            print(error)
        }
        let turnSaberOffUrl = Bundle.main.url(forResource: "SaberOff", withExtension: "mp3")!
        do {
            turnSaberOffAudio = try AVAudioPlayer(contentsOf: turnSaberOffUrl)
            turnSaberOffAudio!.prepareToPlay()
            print("\(turnSaberOffUrl) loaded")
        } catch {
            print(error)
        }

        //...
    }

    //...
}

并像这样使用它:

    @IBAction func lightSaberTapped(_ sender: Any) {
        print("lightsaber open!")

        if !lightsaberModel.isSaberOn {
            //...
            lightsaberModel.turnSaberOnAudio?.play()
            lightsaberModel.isSaberOn = true
        } else {
            //...
            lightsaberModel.turnSaberOffAudio?.play()
            lightsaberModel.isSaberOn = false
        }
    }