Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> iOS

วิธีตรวจจับว่า AVPlayer เล่นวิดีโอจบแล้วใน Swift

ใช้ NotificationCenter ฟัง AVPlayerItemDidPlayToEndTime Notification

โค้ดพื้นฐาน


import AVFoundation

class VideoPlayerViewController: UIViewController {
    var player: AVPlayer!
    var playerLayer: AVPlayerLayer!
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        setupPlayer()
        addObserver()
    }
    
    func setupPlayer() {
        guard let url = Bundle.main.url(forResource: "video", withExtension: "mp4") else { return }
        player = AVPlayer(url: url)
        
        playerLayer = AVPlayerLayer(player: player)
        playerLayer.frame = view.bounds
        playerLayer.videoGravity = .resizeAspect
        view.layer.addSublayer(playerLayer)
        
        player.play()
    }
    
    func addObserver() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(videoDidEnd(_:)),
            name: .AVPlayerItemDidPlayToEndTime,
            object: player.currentItem
        )
    }
    
    @objc func videoDidEnd(_ notification: Notification) {
        print("🎬 Video ended")
        // Action: Replay, Show Next, Dismiss, etc.
        player.seek(to: .zero)
        player.play() // Loop
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

Modern Swift (Combine / Async)


import Combine

// Publisher สำหรับ Video End
extension AVPlayerItem {
    var didPlayToEndTimePublisher: AnyPublisher {
        NotificationCenter.default
            .publisher(for: .AVPlayerItemDidPlayToEndTime, object: self)
            .map { _ in () }
            .eraseToAnyPublisher()
    }
}

// ใช้งาน
var cancellables = Set()
player.currentItem?.didPlayToEndTimePublisher
    .sink { [weak self] in
        print("Video ended via Combine")
        self?.handleVideoEnd()
    }
    .store(in: &cancellables)

การ Loop Video (AVPlayerLooper)


import AVKit

let item = AVPlayerItem(url: videoURL)
let queuePlayer = AVQueuePlayer(playerItem: item)
let looper = AVPlayerLooper(player: queuePlayer, templateItem: item)
// Loop อัตโนมัติ ไม่ต้อง Observer

Observing อื่นๆ ที่มีประโยชน์

  • .AVPlayerItemFailedToPlayToEndTime - เล่นล้มเหลว
  • .AVPlayerItemNewAccessLogEntry - Network Stats
  • .AVPlayerItemNewErrorLogEntry - Error Logs
  • player.currentItem?.status - .readyToPlay, .failed, .unknown

Memory Management

  • ต้อง removeObserver ใน deinit (Memory Leak)
  • ใช้ weak self ใน Closure
  • Combine: เก็บใน cancellables จะ Cancel อัตโนมัติ