概要
画面をタップすると表示・非表示が切り替わるコントロールバーを監視します。
あまりニーズがなさそうな情報ですが、つい最近コントロールバーの表示に合わせて自作UIを表示するという要件が実際にありましたのでメモを兼ねて投稿します。
開発環境
Xcode 12.1
Swift 5
AVPlayerViewControllerのレイヤー構成
AVPlayerViewControllerの動画再生時の画面レイヤーはこのようになっています。
目的のバーはAVViewの配下にあります。
監視対象
バーの表示・非表示の切り替えはAVViewのisHiddenプロパティではなく親のAVTouchIgnoringViewのisHiddenプロパティで行われているのでこいつを監視します。
※Objectice-Cの場合は"isHidden"ではなく"hidden"キーになるようです
実装
ViewController.swift
@IBAction func pressedMoviePlayButton() {
let playerViewController = CustomAVPlayerViewController()
self.present(playerViewController, animated: true) {
playerViewController.player?.play()
playerViewController.find(view: playerViewController.view)
}
}
CustomAVPlayerViewController
private var observers = [NSKeyValueObservation]()
override func viewDidLoad() {
super.viewDidLoad()
let path = Bundle.main.path(forResource: "sample", ofType: "mp4")!
let url: URL = .init(fileURLWithPath: path)
let item: AVPlayerItem = .init(url: url)
let player: AVPlayer = .init(playerItem: item)
self.player = player
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// 監視を解除する
observers.forEach {
$0.invalidate()
}
observers.removeAll()
}
// AVTouchIgnoringViewを探す
func find(view: UIView) {
let targetViewName = "AVTouchIgnoringView"
view.subviews.forEach {
if !self.observers.isEmpty { return }
// isHiddenプロパティをobserveする
if String(describing: type(of: $0)).isEqual(targetViewName) {
self.observers.append($0.observe(\.isHidden, options: .new, changeHandler: { (_, change) in
print("\(change.newValue)")
}))
return
}
self.find(view: $0)
}
}