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 回答