0

目標:
最終的に外部ビデオ ファイル (.mp4、.mpg...) を読み込もうとしています。AVPlayerViewController のインスタンス内。

しかし、私はあらゆる種類の KVO 問題を抱えています。

  1. AVPlayerViewController の KVO オブザーバーは、ここのコンソールに示されているように登録していなくても、常に起動しています (ソース: 以下のコード リストのobserveForKeyPath().print(key path) を参照してください)。

playerController.status playerController.contentDimensions playerController.playingOnExternalScreen playerController.externalPlaybackType playerController.allowsExternalPlayback playerController.hasEnabledVideo playerController.hasEnabledAudio 境界 videoScaled playerController.playingOnExternalScreen view.viewWindowState 境界 playerController.playing

  1. KVO オブザーバー (「timedMetadata」) が登録されていません。どうやら:

self.playerItem!.addObserver(self、forKeyPath: "timedMetadata"、オプション: NSKeyValueObservingOptions.New、コンテキスト: nil)

動作していません:
a) 'observeValueForKeyPath()' は、このオブザーバーに対して発火していません。b) 次の
実行時エラーが発生します (オブザーバーをテストとしてすぐに削除した後):

...理由: 「オブザーバーとして登録されていないため、キー パス "timedMetadata" のオブザーバーを削除できません。」

    class EditShowVideoViewController:AVPlayerViewController {

    var playerItem:AVPlayerItem?

    override func viewDidLoad() {

        self.view.hidden = true

        if let url = NSURL(string: gEditMediumTuple!.medium as! String) {
            let asset = AVURLAsset(URL: url)
            let requestedKeys = Array(arrayLiteral: "tracks", "playable")
            asset.loadValuesAsynchronouslyForKeys(requestedKeys, completionHandler: { ()  in
                // do something
                dispatch_async(dispatch_get_main_queue(), {
                    self.playerItem = AVPlayerItem(asset: asset)
                    self.playerItem!.addObserver(self, forKeyPath: "timedMetadata", options: NSKeyValueObservingOptions.New, context: nil)
                    self.removeObserver(self, forKeyPath:"timedMetadata") //...still runtime error.
                })
            })

        } else {
            showAlert(sender: self.parentViewController!, withTitle: "No Video", withMessage: "No video is found.", alertPurpose: .noVideo)
        }
    }

    override func observeValueForKeyPath(keyPath: String?,
        ofObject object: AnyObject?, change: [String : AnyObject]?,
        context: UnsafeMutablePointer<()>) {
            print(keyPath!)
            guard keyPath == "readyForDisplay" else {return}
            guard let obj = object as? AVPlayerViewController else {return}
            guard let ok = change?[NSKeyValueChangeNewKey] as? Bool else {return}
            guard ok else {return}
            dispatch_async(dispatch_get_main_queue(), {
                self.finishConstructingInterface(obj)
            })

            self.removeObserver(self, forKeyPath:"timedMetadata")
    }

    func finishConstructingInterface (vc:AVPlayerViewController) {
        self.removeObserver(self, forKeyPath:"readyForDisplay")
        self.view.hidden = false
    }

   // ...

}

やりたいことは、ビデオの URL を読み込んで再生することだけです。

救済策が不足している場合は、アドバイスを歓迎します。

4

1 に答える 1

0

実行時エラーは、観測をプレーヤー アイテムに追加しているが、それを自分自身から削除しようとしているために発生します。

オブザーバー コールバックで、キーが観測に属していない場合は、super を呼び出す必要があります。そうしないと、何を壊しているのかわかりません。

クラスをサブクラスとして追加するのではなく、ビデオ VC を子として追加することを検討してください。これにより、論理的に分離され、KVO コールバックの混同が防止されます。

一般的に言えば、コード フロー管理に KVO を使用すると、コードの追跡、デバッグ、保守が非常に難しくなります。別のメカニズムを使用して、純粋に変更の追跡と応答のために KVO を保存することをお勧めします。また、適切に片付けることができるように、観察しているかどうかの少なくともブール値のフラグを保持してください。クラスの割り当てを解除して、ぶら下がっている観測を残すことはできません。

于 2015-10-06T06:51:10.130 に答える