You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVAudioPlayer代理方法实现自动播放下一曲:仅播放两首的问题排查

自动播放下一曲故障修复方案

核心问题分析与修复

  • 代理未重新绑定导致后续播放无回调
    每次调用configure()都会重新初始化AVAudioPlayer,但仅在viewDidLoad中设置过一次代理,后续新创建的player未绑定代理,导致audioPlayerDidFinishPlaying仅在第一首播放完毕后触发,后续歌曲播放完无自动切换逻辑。
    修复:在configure()的player初始化后立即设置代理:

    do {
        // ... 原有代码
        player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: urlString)!)
        guard let player = player else{return}
        player.delegate = self // 添加这行绑定代理
        player.volume = 0.5
        player.play()
    } catch {
        print("error is: \(error.localizedDescription)")
    }
    

    同时删除viewDidLoad中的player!.delegate = self,避免强制解包风险。

  • 本地文件URL创建错误
    使用URL(string: urlString)加载本地文件路径会失败,该方法用于网络URL,本地路径需用URL(fileURLWithPath:)。此错误会导致部分歌曲无法初始化player,表现为播放中断。
    修复:修改configure中的URL初始化代码:

    player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: urlString)!)
    
  • viewDidLayoutSubviews重复触发初始化
    viewDidLayoutSubviews中当holder.subviews.count == 0时调用configure(),而自动切换时会移除所有子视图,导致该方法再次触发configure(),可能造成position异常或重复初始化。
    修复:移除viewDidLayoutSubviews中的configure调用:

    override func viewDidLayoutSubviews() {
        // 注释或删除原有判断代码
    }
    
  • 滑块定时器内存泄漏与逻辑错误
    seekSliderChanged中每次拖动滑块都会创建新的定时器,未清理旧定时器,导致内存泄漏且滑块同步混乱。另外let time = duration/duration等于1,无实际意义。
    修复:先销毁旧定时器,再创建新的同步定时器:

    @objc func seekSliderChanged(_ slider: UISlider) {
        // 先停止旧定时器
        timer?.invalidate()
        
        guard let player = player else { return }
        slider.maximumValue = Float(player.duration)
        player.currentTime = TimeInterval(slider.value)
        
        // 创建新定时器同步滑块
        timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] timer in
            guard let self = self, let player = self.player else {
                timer.invalidate()
                return
            }
            slider.value = Float(player.currentTime)
        }
    }
    

    同时在viewWillDisappear中添加timer?.invalidate(),避免定时器残留。

额外优化建议

  • 避免强制解包player!,统一使用guard let或if let,防止崩溃。
  • configureUI()每次都会重新创建所有UI控件,可改为复用现有控件,仅更新数据,提升性能。
  • 在audioPlayerDidFinishPlaying中添加边界判断,当播放到最后一首时可重置position或停止播放。

内容的提问来源于stack exchange,提问作者A A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:37:19