点击Next按钮时AVAudioPlayer无法触发音频播放的问题求助
音频播放失败问题排查
问题场景
点击「Next」按钮后,文本光标移动至带有星号「*」的单词时,音频应自动播放,但实际无法正常工作。
相关代码
View代码
import AVFoundation import SwiftUI struct SutraView: View { private var audioPlayer: AVAudioPlayer? private mutating func playAVAudio(text: String) { guard let audioFilePath = Bundle.main.path(forResource: "Mokugyo", ofType: "mp3") else { return } do { audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioFilePath)) audioPlayer?.prepareToPlay() } catch { print("Error") } } }
ViewModel代码
import SwiftUI import AVFoundation class SutraViewModel: ObservableObject { // MARK: - Properties private let sutraText: String // text form Model private var audioPlayer: AVAudioPlayer? @Published var itemsToShow: AttributedString? // what will show @Published var currentIndex: Int = 0 // MARK: - Initialization for SutraModel init(model: SutraModel) { self.sutraText = model.sutraText } // MARK: - Public methods func buttonDidPressed() { currentIndex += 1 highlightCurrentWord(text: sutraText) } // MARK: Private methods private func highlightCurrentWord(text: String) { let attributedString = NSMutableAttributedString(string: sutraText) // string can containe design let itemsArray = sutraText.createArrayOfWords() if currentIndex < itemsArray.count { let wordsWithSpaces = sutraText.split(separator: " ") var characterCount = 0 for index in 0..<currentIndex { characterCount += wordsWithSpaces[index].count + 1 } let range = NSRange(location: characterCount, length: itemsArray[currentIndex].count) //attributedString.addAttribute(.backgroundColor, value: UIColor.green, range: range) attributedString.addAttribute(.foregroundColor, value: UIColor.black, range: range) let currentWord = itemsArray[currentIndex] if currentWord.contains("*") { audioPlayer?.play() } } self.itemsToShow = AttributedString(attributedString) } }
问题分析
核心问题是ViewModel里的audioPlayer从未被初始化,一直处于nil状态。当代码执行到audioPlayer?.play()时,可选链调用会直接跳过nil对象的方法执行,自然不会播放音频。另外View中的playAVAudio方法从未被调用,属于冗余代码,对当前逻辑没有帮助。
解决方案
- 在ViewModel初始化阶段完成音频播放器的实例化,确保
audioPlayer有有效对象。 - 完善错误处理逻辑,打印具体错误信息,方便排查音频文件是否存在、路径是否正确。
- 删除View中未使用的音频相关代码,保持代码整洁。
修改后的代码
View代码(简化后)
import AVFoundation import SwiftUI struct SutraView: View { // 移除未使用的audioPlayer和playAVAudio方法 var body: some View { // 你的视图内容 } }
ViewModel代码(修复后)
import SwiftUI import AVFoundation class SutraViewModel: ObservableObject { // MARK: - Properties private let sutraText: String private var audioPlayer: AVAudioPlayer? @Published var itemsToShow: AttributedString? @Published var currentIndex: Int = 0 // MARK: - Initialization init(model: SutraModel) { self.sutraText = model.sutraText // 初始化音频播放器 setupAudioPlayer() } // MARK: - Public methods func buttonDidPressed() { currentIndex += 1 highlightCurrentWord(text: sutraText) } // MARK: Private methods private func setupAudioPlayer() { guard let audioFilePath = Bundle.main.path(forResource: "Mokugyo", ofType: "mp3") else { print("错误:找不到Mokugyo.mp3文件,请检查文件名和路径") return } do { audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioFilePath)) audioPlayer?.prepareToPlay() print("音频播放器初始化成功") } catch { print("音频初始化失败:\(error.localizedDescription)") } } private func highlightCurrentWord(text: String) { let attributedString = NSMutableAttributedString(string: sutraText) let itemsArray = sutraText.createArrayOfWords() guard currentIndex < itemsArray.count else { return } let wordsWithSpaces = sutraText.split(separator: " ") var characterCount = 0 for index in 0..<currentIndex { characterCount += wordsWithSpaces[index].count + 1 } let range = NSRange(location: characterCount, length: itemsArray[currentIndex].count) attributedString.addAttribute(.foregroundColor, value: UIColor.black, range: range) let currentWord = itemsArray[currentIndex] if currentWord.contains("*") { // 此时audioPlayer已初始化,调用play会正常执行 audioPlayer?.play() } self.itemsToShow = AttributedString(attributedString) } }
额外提示
- 确保
Mokugyo.mp3已正确添加到项目中,且在Target的Build Phases -> Copy Bundle Resources列表里能找到该文件。 - 如果需要重复播放音频,可以在调用
play()前再次调用prepareToPlay(),避免音频播放完毕后无法触发再次播放的问题。
内容的提问来源于stack exchange,提问作者Kuralay Biehler
相关产品推荐
相关产品推荐

