3

我正在使用 AVPlayer 的 -addBoundaryTimeOserverForTimes:queue:usingBlock: 在视频中的特定时间执行一些代码(在这种情况下,我想要在视频达到其持续时间时取消隐藏按钮。代码如下:

- (void)viewWillAppear:(BOOL)animated
{
    ...

    _player = [AVPlayer playerWithURL:videoURL];

    AVPlayerLayer *newPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
    [newPlayerLayer setFrame:_videoView.bounds];
    [_videoView.layer addSublayer:newPlayerLayer];

    _observer = [_player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:_player.currentItem.duration]] queue:NULL usingBlock:^{
        [someButton setHidden:NO];
    }];

    ...
}

无论出于何种原因,有时代码块会触发并且按钮变得可见,有时则不会。无法在此行为中找到模式。它经常(几乎总是)在模拟器中发生,偶尔在设备上发生。有没有人遇到过这个问题?任何想法可能会发生什么?

编辑

此外,如果我在块上设置断点,它总是会触发。

4

2 回答 2

0

对于那些想要观察播放器何时结束的人:

我大约每年浏览一次这个问题,因为我总是忘记对我有用的修复程序。这次我在 macOS 上遇到了这个问题。我看到了同样的行为,观察者块有时不会被调用。当我从正在调试的应用程序切换回 Xcode 时,该块突然触发。这可能与 OP 所描述的在块中设置断点有关。

但是,这是解决方法:只需AVPlayerItemDidPlayToEndTimeNotification按照此答案中的说明切换到。但是请注意,顾名思义,通知的对象是玩家的当前项目,而不是玩家本身!

因为这个通知在项目的结束时间触发,而不是观察一些“边界时间”,forwardPlaybackEndTime如果您需要另一个时间而不是项目的实际结束时间,即持续时间,只需设置项目的时间。

于 2018-12-06T10:04:10.813 回答
0

主队列有时不调用。您可以使用子队列,并在子队列的块中调用主队列。

// dispatch queue setting
dispatch_queue_t subQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

// notification setting
__block id blockObserver;
blockObserver = [self.queuePlayer addBoundaryTimeObserverForTimes:boundary
                 queue:subQueue // if NULL use mainQueue

  usingBlock:^{
    // do something
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_async(mainQueue, ^{
        // do something
    });
}];
于 2018-05-20T02:42:33.917 回答