gpt4 book ai didi

ios - 如何使用单个按钮启动和停止音频?

转载 作者:可可西里 更新时间:2023-11-01 02:01:34 26 4
gpt4 key购买 nike

我正在构建一个 sleep 定时器应用程序,它允许使用 9 种不同的声音来帮助您休眠。我最不需要的是能够在我点击按钮时播放声音,并在我再次按下按钮时停止相同的声音。我试过这样做:

@IBAction func heavyThunderBtnPressed(_ sender: UIButton) {
heavyThunderBtn.isSelected = true
toggleButton(button: sender, onImage: #imageLiteral(resourceName: "thunderstorm_selected"), offImage: #imageLiteral(resourceName: "thunderstorm_unselected"))
numberOfPresses += 1


if numberOfPresses % 2 == 0 || numberOfPresses == 1 && numberOfPresses != 2 {
do {
rainAudioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "thunder", ofType: "mp3")!))
rainAudioPlayer.prepareToPlay()
rainAudioPlayer.play()
}
catch {
print(error)
}
}
else {
rainAudioPlayer.stop()

}
}

但它允许我按下按钮,它会播放音频并且按钮会更改为我选择的颜色以指示它已打开。然后当我再次按下它时,音频重新开始并继续播放,然后当我再次按下它时,它停止但按钮再次变为蓝色表示它已打开。所以这就是我将其更改为的内容,但是每次按下按钮播放音频时我都会崩溃。我得到的错误是“EXC_BAD_ACCESS(代码 = 1,地址 = 0 x 48)”

import UIKit
import AVFoundation

class RainSoundsViewController: UIViewController {

var rainAudioPlayer = AVAudioPlayer()
var numberOfPresses = 0
var tappedAgain: Bool! = false

var heavyThunderOffImage = UIImage()

@IBOutlet weak var backgroundView: UIView!

@IBOutlet weak var heavyThunderBtn: UIButton!

@IBOutlet weak var lightRainBtn: UIButton!

@IBOutlet weak var rainOnRoofBtn: UIButton!


override func viewDidLoad() {
super.viewDidLoad()

heavyThunderOffImage = #imageLiteral(resourceName: "thunderstorm_unselected")

heavyThunderBtn.isSelected = false

backgroundView.layer.cornerRadius = 10
backgroundView.layer.masksToBounds = true


}

@IBAction func dismissPopup(_ sender: Any) {
dismiss(animated: true, completion: nil)
}

@IBAction func heavyThunderBtnPressed(_ sender: UIButton) {
heavyThunderBtn.isSelected = true
toggleButton(button: sender, onImage: #imageLiteral(resourceName: "thunderstorm_selected"), offImage: #imageLiteral(resourceName: "thunderstorm_unselected"))
numberOfPresses += 1


if rainAudioPlayer.isPlaying {

do {
rainAudioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "thunder", ofType: "mp3")!))
rainAudioPlayer.prepareToPlay()
rainAudioPlayer.play()
}
catch {
print(error)
}
}
else {
rainAudioPlayer.stop()

}
}

最佳答案

您的代码中最重要的缺陷存在于这一行中:

var rainAudioPlayer = AVAudioPlayer()

初始化器 init() 没有为 AVAudioPlayer 明确定义,结果是不可预测的。事实上,这个初始化器创建了一个完全无用的对象。

并且 rainAudioPlayer 变成非可选的,所以你不能检查它是否正确初始化。

让它成为可选的。不要给它一个无用的初始值。

var rainAudioPlayer: AVAudioPlayer?

随着这一变化,您的代码的其他一些部分需要修复。例如,if 语句的条件为:

if rainAudioPlayer?.isPlaying ?? false {

或者:

if let player = rainAudioPlayer, player.isPlaying {

带有一些其他建议的完整代码:

import UIKit
import AVFoundation

class RainSoundsViewController: UIViewController {

var rainAudioPlayer: AVAudioPlayer? //### You should not instantiate a useless instance.
var numberOfPresses = 0
var tappedAgain: Bool = false //<- You have no reason to make this Implicitly Unwrapped Optional.

var heavyThunderOffImage: UIImage! //<- Do you really need this?

@IBOutlet weak var backgroundView: UIView!

@IBOutlet weak var heavyThunderBtn: UIButton!

@IBOutlet weak var lightRainBtn: UIButton!

@IBOutlet weak var rainOnRoofBtn: UIButton!


override func viewDidLoad() {
super.viewDidLoad()

heavyThunderOffImage = #imageLiteral(resourceName: "thunderstorm_selected")

heavyThunderBtn.isSelected = false

backgroundView.layer.cornerRadius = 10
backgroundView.layer.masksToBounds = true
}

@IBAction func dismissPopup(_ sender: Any) {
dismiss(animated: true, completion: nil)
}

@IBAction func heavyThunderBtnPressed(_ sender: UIButton) {
heavyThunderBtn.isSelected = true
toggleButton(button: sender, onImage: #imageLiteral(resourceName: "thunderstorm_selected"), offImage: #imageLiteral(resourceName: "thunderstorm_unselected"))
numberOfPresses += 1

if rainAudioPlayer?.isPlaying ?? false { //### `rainAudioPlayer` is now Optional.

do {
rainAudioPlayer = try AVAudioPlayer(contentsOf: Bundle.main.url(forResource: "thunder", withExtension: "mp3")!) //<- You can use `url(forResource:withExtension:)`.
//`play()` internally calls `prepareToPlay()`, you have no need to call it here.
rainAudioPlayer?.play()
}
catch {
print(error)
}
}
else {
rainAudioPlayer?.stop() //<- Here, `rainAudioPlayer` is NOT playing, do you need to stop it?
}
}

//...
}

我没有检查此代码的其他部分是否按您预期的那样工作,但不会再导致 EXC_BAD_ACCESS

关于ios - 如何使用单个按钮启动和停止音频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45897025/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com