2

AVFoundation AVPlayer を使用して境界時間のオブザーバーを追加すると、奇妙な問題が発生します。

 player = AVPlayer.playerWithURL(NSURL.URLWithString(someurl))
 player.play()
 player.addBoundaryTimeObserverForTimes([NSValue.valueWithCMTime(CMTimeMake(1,1))], queue: nil, usingBlock: -> { puts 'success' } )

このコードを XCode で実行すると、オブザーバーを追加するとデバッグ用のアセンブラー コードに落ちますが、コンソールにはエラーが表示されません。誰かがそのような問題に直面しましたか?

4

3 に答える 3

1

私はこのように使用していますが、うまくいきます:

__block AVPlayer* blockPlayer = self.player;        //player is already initialised and set up; 
__block id obs;

// Setup boundary time observer to trigger when audio really begins,
// specifically after 1/3 of a second playback

obs = [self.player addBoundaryTimeObserverForTimes: @[[NSValue valueWithCMTime:CMTimeMake(1, 10)]]
                                             queue:NULL
                                        usingBlock:^{

                                           // Raise a notificaiton when playback has started
                                           [[NSNotificationCenter defaultCenter] postNotificationName:PLAYBACK_STARTED_NOTIFICATION object:nil];

                                           // Remove the boundary time observer
                                           [blockPlayer removeTimeObserver:obs];
                                       }];
于 2014-08-20T15:05:55.777 に答える
0

ドキュメントをよく読むと、このメソッドが次を返すことがわかります。

戻り値: 監視を停止するために removeTimeObserver: に引数として渡す不透明なオブジェクト。

そして後でそれ:

プレイヤーが時間オブザーバーを呼び出したい限り、戻り値を保持する必要があります。このメソッドの各呼び出しは、removeTimeObserver への対応する呼び出しとペアにする必要があります。

あなたの問題は、メソッドの戻り値を保持していないことです。単にメソッドを呼び出しているため、時間オブザーバーがプレーヤーによって呼び出されていません。

__block 変数を使用すると、実際にここで機能するはずです

player = AVPlayer.playerWithURL(NSURL.URLWithString(someurl))
player.play()

__block id observer = player.addBoundaryTimeObserverForTimes([NSValue.valueWithCMTime(CMTimeMake(1,1))], queue: nil, usingBlock: ->
{
    puts 'success'
    player.removeTimeObserver(observer) // IMPORTANT, but careful. Read below*
} )

以下*: Apple が強調しているように、removeTimeObserver を呼び出す必要があります。私にとって最も理にかなっている場所は完了ブロックですが、少なくとも Obj C と Swift および他のほとんどの言語では、これにより保持サイクルが発生します。 . Obj C と Swift では、ブロック内から安全に参照できるように、オブザーバーとプレーヤーをブロック変数として宣言することで、これを回避できます。

removeTimeObserver メソッドを安全に呼び出す場所が他にある場合は、それについて心配する必要はありません。

とにかく、上記のコードは、プレーヤーが曲/ビデオに 1 秒入ったときにブロックを実行します。

また、次の点にも注意してください。

AV Foundation は、渡された間隔または境界ごとにブロックを呼び出すことを保証しません。前に呼び出されたブロックの実行が完了していない場合、AV Foundation はブロックを呼び出しません。したがって、ブロックで実行する作業がシステムに過度の負担をかけないようにする必要があります。

これはあなたには当てはまらないと思いますが、複数の時間間隔/境界を追加した他の誰かに当てはまるかもしれません.

于 2015-08-16T05:32:30.003 に答える
-1

おそらく、パラメーターとして渡されるキューが本当に必要です

これを試して:

dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

[player addBoundaryTimeObserverForTimes:[NSValue.valueWithCMTime(CMTimeMake(1,1))]
                                  queue: myQueue
                             usingBlock: -> { puts 'success' }];
于 2013-02-27T23:05:23.437 に答える