LoginSignup
5
1

More than 5 years have passed since last update.

AVContentProposalは本当に便利なのか

Last updated at Posted at 2017-12-04

AVContentProposalとは

tvOS10から登場した、次のエピソードの訴求をクールかつシンプルに実装することができるAVKitのAPIです。
avcontentproposal001.gif

問題

以前こういう記事を書きまして、AVContentProposalちゃんと動かないじゃん!という問題提起をしました。transitionアニメーション中にMENUを押して戻ると表示がおかしくなります。シミュレータではオートレイアウトのエラーが出てクラッシュします。

avcontentproposal002.gif

tvOS11で試したところ、依然として問題が継続していました。

2017-11-18 21:53:54.683980+0900 TVOSTest[11885:456841] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors and because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'

ワークアラウンドを実装できましたので共有します。

ワークアラウンド

原因はAVPlayerViewControllerがすでにプレイヤーがいなくなっていることにContentProposalViewControllerが気づかないのが原因なので、

  • 気づかせてあげる
  • 状況がハッキリするまではボタンなどUIを表示しない

の2点が解決方法です。要するに、地道にフラグ管理するということになります。

class ContentProposalViewController: AVContentProposalViewController {
    var shouldDismiss: Bool = false {
        didSet { dismissIfNeeded() }
    }
    @IBOutlet private var button: UIButton! {
        didSet { button.alpha = 0.0 }
    }
    @IBOutlet private var textView: UITextView! {
        didSet { textView.alpha = 0.0 }
    }
    override var preferredFocusEnvironments: [UIFocusEnvironment] {
        return [button]
    }
    override var preferredPlayerViewFrame: CGRect {
        return CGRect(x: 432, y: 20, width: 1056, height: 594)
    }
    @IBAction private func button(sender: UIButton!) {
        dismissContentProposal(for: .accept, animated: true, completion: nil)
    }
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        if !shouldDismiss {
            UIView.animate(withDuration: 0.2) {
                self.button.alpha = 1.0
                self.textView.alpha = 1.0
            }
        } else {
            dismissIfNeeded()
        }
    }
    private func dismissIfNeeded() {
        if shouldDismiss {
            DispatchQueue.main.async { [weak self] in
                self?.button?.alpha = 0.0
                self?.textView?.alpha = 0.0
                self?.dismissContentProposal(for: .reject, animated: false, completion: nil)
            }
        }
    }
    deinit {
        print(#function)
    }
}

これで、MENU押して戻った時に見た目がおかしくなることはなくなりました。シミュレータでもクラッシュしません🎉

avcontentproposal003.gif

まとめ

「AVContentProposalは本当に便利なのか?」

上記のようなワークアラウンドをすれば、とっても便利です!

以前作った以下のサンプルアプリを更新しておきましたのでご興味ある方はご覧ください。
https://github.com/toshi0383/tvOS-10-Sampler

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1