커스텀 플레이어를 구현하기 위해서는 재생되는 객체를 보여주기 위한 역할을 하는 것이 필요한데 그 역할을 해주는 것이 AVPlayerLayer이다.
CALayer를 상속한 class로 선언되어 있다.
공식 문서에, 이 객체의 일반적인 사용 예제 코드가 쓰여있다.
/// A view that displays the visual contents of a player object.
class PlayerView: UIView {
// Override the property to make AVPlayerLayer the view's backing layer.
override static var layerClass: AnyClass { AVPlayerLayer.self }
// The associated player object.
var player: AVPlayer? {
get { playerLayer.player }
set { playerLayer.player = newValue }
}
private var playerLayer: AVPlayerLayer { layer as! AVPlayerLayer }
}
그래서 AVPlayerLayer를 layer로 두고, AVPlayer를 통한 영상 재생 인터페이스를 제공하는 뷰를 다음과 같이 구성했다. 다만, 영상 재생을 위한 AVPlayer 실제 객체는 외부에서 세팅해주도록 했다.
import UIKit
import AVFoundation
final class PlayerView: UIView {
// MARK: - Properties
// Override the property to make AVPlayerLayer the view's backing layer.
override static var layerClass: AnyClass { AVPlayerLayer.self }
// The associated player object.
var player: AVPlayer? {
get { playerLayer?.player }
set { playerLayer?.player = newValue }
}
private var playerLayer: AVPlayerLayer? { layer as? AVPlayerLayer }
// MARK: - Initializer
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
// MARK: View Life Cycle
override func layoutSubviews() {
super.layoutSubviews()
playerLayer?.frame = bounds
}
// MARK: Methods
func setVideoFillMode(_ mode: AVLayerVideoGravity) {
playerLayer?.videoGravity = mode
}
func play() {
playerLayer?.player?.play()
}
func pause() {
playerLayer?.player?.pause()
}
func seek(to time: CMTime) {
playerLayer?.player?.seek(to: time)
}
func isPlaying() -> Bool {
return playerLayer?.player?.rate != 0 && playerLayer?.player?.error == nil
}
}