Swift: AVAudioPlayer не воспроизводится, возможна ошибка с потоками? - PullRequest
0 голосов
/ 09 мая 2019

В настоящее время я работаю над приложением, которое воспроизводит аудиоклип на основе состояния изображения / объекта.

В настоящее время я получаю этот код ошибки.

Тема 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 голосов
/ 10 мая 2019

Это то, что вы никогда не должны делать:

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
        }
    }
...