我正在构建一个包含多个 View Controller 的应用程序。我需要控制所有音乐,所以我创建了一个专门的音乐类,我用它来设置/播放/停止/暂停。
我已经录制了音频问题和答案,我需要能够播放 question 和 answer mp3 文件。
所以我相信这里有几种方法来完成这个委托(delegate)和协议(protocol),使用 func audioPlayerDidFinishPlaying 和使用闭包。据我所知,闭包是我想要实现的最佳选择。
我在 MakeMusic 课上的出发点是:
class MakeMusicClass : NSObject, AVAudioPlayerDelegate {
static let shared = MakeMusicClass()
var audioPlayer = AVAudioPlayer()
override init() { }
func setup(Selection: String) {
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: Selection, ofType: "mp3")!))
audioPlayer.prepareToPlay()
audioPlayer.delegate=self
} catch {
print (error)
}
}
func play() {
audioPlayer.play()
}
我的调用文件是:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
MakeMusicClass.shared.setup(Selection: "Question11")
MakeMusicClass.shared.play()
MakeMusicClass.shared.setup(Selection: "Answer11")
MakeMusicClass.shared.play()
为了让它工作,我知道我需要为被调用的类添加一个闭包:
func play() {
var closure = { in
audioPlayer.play()
}
}
我需要更新我需要调用函数的位置,例如:
override func viewDidLoad() {
super.viewDidLoad()
MakeMusicClass.shared.setup(Selection: "Question11")
MakeMusicClass.shared.play() {
MakeMusicClass.shared.setup(Selection: "Answer11")
MakeMusicClass.shared.play()
}
我花了很长时间试图解决这个问题,但我很挣扎。我的代码显然不起作用,因为我缺少一些基本的东西。我尝试过传递 void 和参数,但我不明白应该传递哪些参数。我最接近的是使用 makemusic 类中的 audioPlayerDidFinishPlaying 触发下一个音频文件,但我不知道这是理想的。
Best Answer-推荐答案 strong>
我认为您最好的选择是在您的 MakeMusicClass 中使用 Array 作为初始化程序,例如一个问题和答案,然后使用 AVAudioPlayerDelegate 触发下一个文件,我认为这是你想要得到的(非常接近 ^________*)。
例如:
class AudioLooper: NSObject, AVAudioPlayerDelegate {
var debugView = true
var audioLoopPlayer: AVAudioPlayer!
var audioFileIndex: Int = 0
var audioFileArray: [String] = []
//-------------------------------------------------
//MARK: Audio Player Initialisation & Functionality
//-------------------------------------------------
/// Function To Initialise The Audio Loop Player
///
/// - Parameter audioFiles: [String] - The Array Of Audio Files To Play
func initAudioPlayerWith(audioFiles: [String]) {
audioFileArray = audioFiles
if debugView { print("Audio Files To Play In Sequence == \(audioFileArray)") }
}
/// Function To Play An Array Of Audio Files
///
/// - Parameter index: (Int) - The Current Index Of The Audio Sequence
func playAudioLoopAt(index: Int) {
let currentAudioFile = "\(audioFileArray[audioFileIndex])"
if let audioFilePath = Bundle.main.path(forResource: currentAudioFile, ofType: "mp3"){
do {
let audioFileUrl = NSURL.fileURL(withPath: audioFilePath)
// Set An Instance Of AVAudioSession Which Allows Playback Even When Device Is Muted
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
audioLoopPlayer = try AVAudioPlayer(contentsOf: audioFileUrl)
audioLoopPlayer.prepareToPlay()
audioLoopPlayer.delegate = self
audioLoopPlayer.play()
if debugView { print("laying \(currentAudioFile) ") }
audioFileIndex += 1
} catch {
print("Error Playing Audio")
}
} else {
print("Error Finding File: \(currentAudioFile)")
}
}
/// Function To Continue The Audio Sequence
@objc func continueAudioLoop(){
playAudioLoopAt(index: audioFileIndex)
}
/// Function To Stop The Audio Looop Player
func stopAudioPlayer() {
if audioLoopPlayer != nil {
audioFileIndex=0
audioLoopPlayer.stop()
audioLoopPlayer = nil
}
}
//-----------------------------
//MARK: AVAudio Player Delegate
//-----------------------------
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if audioFileIndex < audioFileArray.count {
self.perform(#selector(continueAudioLoop), with: self, afterDelay: 0.5)
}else{
audioFileIndex=0
}
}
}
在我的示例中,您只需像这样初始化:
audioLooper = AudioLooper()
audioLooper?.initAudioPlayerWith(audioFiles: ["question", "answer"])
audioLooper?.playAudioLoopAt(index: 0)
audioLooper 声明如下:var audioLooper:AudioLooper?
显然我的示例不是单例,但它应该让您了解如何调整 MakeMusicClass 以使其适合...
你也可以像这样添加一个 Delegate 方法来通知 ViewController 音频已经完成或执行一些其他任务,比如更新下一个问题等,例如:
@objc protocol AudioLooperDelegate {
@objc optional func update()
}
然后在你的 ViewController 中:
var delegate: AudioLooperDelegate?
然后在 AudioLooper 类中,您可以在需要的地方添加委托(delegate)方法,例如:
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if audioFileIndex < audioFileArray.count {
self.perform(#selector(continueAudioLoop), with: self, afterDelay: 0.5)
}else{
audioFileIndex=0
delegate?.updateUI!()
}
}
}
关于ios - Swift 需要关闭音频播放器,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/49081121/
|