anz blog

AVPlayerViewController で謎の AutoLayout 制約エラー

2018-04-10 #Swift #AutoLayout

内容はタイトルの通りで、別に回避策もなにもなくただの愚痴です(汗)

AVPlayerViewControllerを使って動画再生させているんだけど謎のAutoLayout制約エラーがでて気になりすぎるんだが...

です

環境

  • Xcode v9.3
  • Swift v4.1

本題

とりあえずやりたかったことは...
AVPlayerViewControllerをそのままつかうのではなくて、
とあるUIViewのなかに表示させる形で使いたいっていうもの。
ってことで、下記のように組んでみました。

class ViewController: UIViewController {

    @IBOutlet weak var playerViewContainer: UIView!
    
    private let playerViewController: AVPlayerViewController = AVPlayerViewController()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        guard let bundlePath = Bundle.main.path(forResource: "movie", ofType: "mp4") else {
            return
        }
        
        self.playerViewController.player = AVPlayer(url: URL(fileURLWithPath: bundlePath))
        self.playerViewController.view.translatesAutoresizingMaskIntoConstraints = false
        self.playerViewController.videoGravity = AVLayerVideoGravity.resizeAspect.rawValue
        self.playerViewController.view.frame = self.view.bounds
        self.addChildViewController(self.playerViewController)
        self.playerViewContainer.addSubview(self.playerViewController.view)
        self.playerViewController.didMove(toParentViewController: self)
        NSLayoutConstraint.activate([
            self.playerViewController.view.topAnchor.constraint(equalTo: self.playerViewContainer.topAnchor),
            self.playerViewController.view.leftAnchor.constraint(equalTo: self.playerViewContainer.leftAnchor),
            self.playerViewController.view.rightAnchor.constraint(equalTo: self.playerViewContainer.rightAnchor),
            self.playerViewController.view.bottomAnchor.constraint(equalTo: self.playerViewContainer.bottomAnchor),
        ])
        self.playerViewController.player?.play()
    }
}

ざっくり書くと... AVPlayerViewController.viewを対象のUIView.addSubview()とすることで、そこで表示ができるでしょ?というノリです。

実際、これで良い感じに再生されます💪

ところが Xcode の Debug area の方には Auto layout の制約エラーがでまくりです。

[LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. ( "<NSLayoutConstraint:0x6040002818b0 'UISV-canvas-connection' UILayoutGuide:0x6040001bbf20'UIViewLayoutMarginsGuide'.top == _UILayoutSpacer:0x6040001cc3f0'UISV-alignment-spanner'.top (active)>", "<NSLayoutConstraint:0x604000281900 'UISV-canvas-connection' UILayoutGuide:0x6040001bbf20'UIViewLayoutMarginsGuide'.bottom == _UILayoutSpacer:0x6040001cc3f0'UISV-alignment-spanner'.bottom (active)>", "<NSLayoutConstraint:0x6040002810e0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x6040001bbf20'UIViewLayoutMarginsGuide']-(12)-| (active, names: '|':UIStackView:0x7fc27ac034f0 )>", "<NSLayoutConstraint:0x604000280af0 'UIView-Encapsulated-Layout-Height' UIStackView:0x7fc27ac034f0.height == 0 (active)>", "<NSLayoutConstraint:0x604000281040 'UIView-topMargin-guide-constraint' V:|-(12)-[UILayoutGuide:0x6040001bbf20'UIViewLayoutMarginsGuide'] (active, names: '|':UIStackView:0x7fc27ac034f0 )>" )

Will attempt to recover by breaking constraint <NSLayoutConstraint:0x604000281900 'UISV-canvas-connection' UILayoutGuide:0x6040001bbf20'UIViewLayoutMarginsGuide'.bottom == _UILayoutSpacer:0x6040001cc3f0'UISV-alignment-spanner'.bottom (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

UIViewに追加しているとこで、なにかしらこわれるのか?🤔
とかおもって、ごにょごにょしても全然消えなかったので、ちょっと普通の使い方してみました。

普通の画面と同じように、AVPlayerViewControllerに遷移しちゃう方法です。

guard let bundlePath = Bundle.main.path(forResource: "movie", ofType: "mp4") else {
    return
}

self.playerViewController.player = AVPlayer(url: URL(fileURLWithPath: bundlePath))
self.playerViewController.videoGravity = AVLayerVideoGravity.resizeAspect.rawValue
self.present(self.playerViewController, animated: true, completion: nil)

...だめでした。これでも同じようにエラーがでる。
ってことで、僕の中での結論はAVPlayerViewControllerのバグということに
まぁ、表示崩れも特になく動いているとおもうので全然いいのですけど、
すごく気になりますし、すごく邪魔ですよね...(汗)

なにか解決策をしっているかたは教えて欲しい...

参考

Building a Basic Playback App - developer.apple.com
ここにあるのをコピペしても出るんだからもうしゃーない感ある