Swift中KikiAudioPlayer内AVAudioPlayer未初始化问题问询
问题根源分析
你遇到的<uninitialized>问题核心在于**AVAudioPlayer不能通过无参初始化创建可用实例**。
你在KikiAudioPlayer里写的var audioPlayer = AVAudioPlayer(),只是调用了NSObject的默认空初始化,并没有真正完成AVAudioPlayer的初始化逻辑——AVAudioPlayer必须依赖音频资源(URL或Data)才能生成可工作的播放器实例。这个写法只会生成一个空壳对象,内部没有加载任何音频相关资源,所以调试时会显示<uninitialized>,调用play()/pause()自然没有响应。
解决方案
步骤1:修复KikiAudioPlayer的初始化逻辑
把audioPlayer改为可选类型,并添加带音频资源的初始化方法,真正完成播放器的初始化:
class KikiAudioPlayer: NSObject, AVAudioPlayerDelegate { var audioPlayer: AVAudioPlayer? // 改为可选类型,避免空初始化的无效实例 var updater: CADisplayLink? // 注意这里也要确保updater是可选类型,避免未初始化问题 weak var delegate: KikiAudioPlayerDelegate? // 假设你有对应的代理协议 // 添加初始化方法,传入音频文件URL init(audioURL: URL) throws { super.init() audioPlayer = try AVAudioPlayer(contentsOf: audioURL) audioPlayer?.delegate = self audioPlayer?.prepareToPlay() // 提前加载音频到内存,优化播放启动速度 } func play() { audioPlayer?.play() delegate?.audioPlayerPlayingStatusChanged(isPlaying: true) updater = CADisplayLink(target: self, selector: #selector(updateDelegate)) updater?.add(to: RunLoop.current, forMode: .common) setWaiting(to: false) } func pause() { audioPlayer?.pause() delegate?.audioPlayerPlayingStatusChanged(isPlaying: false) updater?.invalidate() setWaiting(to: true) } @objc private func updateDelegate() { // 你的更新逻辑 } private func setWaiting(to isWaiting: Bool) { // 你的状态设置逻辑 } } // 补充代理协议(如果之前没定义) protocol KikiAudioPlayerDelegate: AnyObject { func audioPlayerPlayingStatusChanged(isPlaying: Bool) }
步骤2:在AudioBarView中正确初始化播放器
确保传入有效的音频资源URL,同时处理初始化可能出现的错误:
class AudioBarView: UIView { @IBOutlet weak var playPauseButton: UIButton! @IBOutlet weak var nowPlayingSongLabel: UILabel! var kikiAudioPlayer: KikiAudioPlayer? override func awakeFromNib() { super.awakeFromNib() // 替换成你自己的音频文件名和格式 guard let audioURL = Bundle.main.url(forResource: "your-audio-file", withExtension: "mp3") else { print("错误:未找到音频文件,请检查文件是否已添加到项目target") return } do { kikiAudioPlayer = try KikiAudioPlayer(audioURL: audioURL) } catch { print("初始化音频播放器失败:\(error.localizedDescription)") } } @IBAction func playPauseButtonPressed(_ sender: UIButton) { let playImage = UIImage(systemName: "play.fill") guard let player = kikiAudioPlayer else { print("播放器未初始化,无法执行播放/暂停操作") return } if playPauseButton.currentImage == playImage { playPauseButton.setImage(UIImage(systemName: "pause.fill"), for: .normal) player.play() } else { playPauseButton.setImage(UIImage(systemName: "play.fill"), for: .normal) player.pause() } } }
额外注意事项
- 确保音频文件已正确添加到项目的Target Membership中,否则
Bundle.main.url会返回nil - 一定要处理
AVAudioPlayer初始化的错误,比如音频格式不支持、文件损坏等情况 - 使用
prepareToPlay()可以提前加载音频数据,减少首次播放的延迟
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

