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

SwiftUI中AVPlayerItemDidPlayToEndTime通知未触发问题求助

AVPlayerItemDidPlayToEndTime通知不触发的修复方案

核心问题分析

你的代码存在两个关键错误导致通知无法触发:

  1. 观察者与处理函数归属不匹配:你将通知观察者注册为View实例(self),但处理函数playerDidFinishPlaying属于VideoPlayerCoordinator类,通知无法正确分发到目标函数。
  2. 初始化顺序错误:你先注册通知,之后才初始化coordinator,导致通知绑定的观察者实例不存在,同时未指定目标playerItem,进一步降低通知触发的准确性。

修正后的代码实现

1. 调整View的.onAppear逻辑(先初始化协调器再注册通知)

.onAppear {
    let playerItem = AVPlayerItem(url: videoURL!)
    let videoOutput = AVPlayerItemVideoOutput(pixelBufferAttributes: nil)
    playerItem.add(videoOutput)
    
    let player = AVPlayer(playerItem: playerItem)
    self.player = player
    
    // 优先初始化coordinator,确保实例已创建
    self.coordinator = VideoPlayerCoordinator(videoOutput: videoOutput, playerItem: playerItem)
    
    // 注册通知:观察者设为coordinator,object指定当前playerItem
    NotificationCenter.default.addObserver(
        self.coordinator!,
        selector: #selector(VideoPlayerCoordinator.playerDidFinishPlaying),
        name: .AVPlayerItemDidPlayToEndTime,
        object: playerItem
    )
    
    player.play()
}

2. 优化Coordinator的通知处理函数(增强鲁棒性)

@objc func playerDidFinishPlaying(_ notification: Notification) {
    guard let finishedItem = notification.object as? AVPlayerItem else { return }
    print("视频播放结束:\(finishedItem)")
    // 此处添加播放结束后的业务逻辑,比如重置播放状态、触发回调等
}

3. 添加通知移除逻辑(避免内存泄漏)

在View的.onDisappear中移除观察者:

.onDisappear {
    guard let coordinator = coordinator, let playerItem = coordinator.playerItem else { return }
    NotificationCenter.default.removeObserver(
        coordinator,
        name: .AVPlayerItemDidPlayToEndTime,
        object: playerItem
    )
}

额外注意事项

  • 确保player和playerItem被正确持有(比如用@State或@ObservedObject修饰),避免实例提前释放导致通知无法触发。
  • 如果视频开启了循环播放模式,AVPlayerItemDidPlayToEndTime通知不会触发,需检查播放设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:33:25