当单元格移出屏幕时如何停止单元格中的 AVPlayer 播放
How to stop AVPlayer playback in cell when the cell has moved offscreen
场景:我有一个 tableView
有很多单元格。每个单元格将包含一个 AVPlayer 来播放视频。一旦用户按下单元格上的播放按钮,就会创建 AVPlayer。我希望 AVPlayer 停止播放它的视频,并在它的单元格移出屏幕时 完全 删除。
问题:当单元格移出屏幕时,媒体仍会播放。因此,当我尝试根据需要移除播放器时,我的应用程序崩溃并出现错误
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An instance of AVPlayer cannot remove a time observer that was added by a different instance of AVPlayer.'
播放器的创建方式:
(在单元格中)
-(void)addPlayer {
if (!self.player) {
// This is my custom init method
self.player = [[AVPlayer alloc] initWithFrame:self.container.bounds contentURL:mediaURL];
[self.player setUserInteractionEnabled:YES];
[self.container setUserInteractionEnabled:YES];
[self.container addSubview:self.player];
}
}
如何添加 addTimeObserver:
-(void)beginObservingTime {
// This will monitor the current time of the player
__weak STPlayer *weakSelf = self;
self.observerToken = [self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1.0, NSEC_PER_SEC) queue:nil usingBlock:^ (CMTime time) {
if (CMTimeGetSeconds(time) > self.playbackTime) {
// done buffering
[weakSelf updatePlaybackTime:CMTimeGetSeconds(time)];
[weakSelf.player removeTimeObserver:weakSelf.observerToken];
[weakSelf hideActivityIndicator];
}
}];
}
如何删除播放器:
(在 UITableViewController 中)
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(FeedCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[cell breakDownPlayer];
}
(在单元格中)
-(void)breakDownPlayer {
[self.player breakDown];
}
(在玩家子类中)
-(void)breakDown {
[self.player removeTimeObserver:self.observerToken];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
}
问题:一旦 didEndDisplayingCell
被调用且应用程序未崩溃,如何从 UITableViewCell
中删除播放器?
您是否尝试过在 didEndDisplayingCell 方法中将播放器设置为 nil?
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(FeedCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (cell.player.rate != 0 && (cell.player.error == nil)) {
// player is playing
cell.playButton.hidden = NO;
cell.player = nil;
}
}
场景:我有一个 tableView
有很多单元格。每个单元格将包含一个 AVPlayer 来播放视频。一旦用户按下单元格上的播放按钮,就会创建 AVPlayer。我希望 AVPlayer 停止播放它的视频,并在它的单元格移出屏幕时 完全 删除。
问题:当单元格移出屏幕时,媒体仍会播放。因此,当我尝试根据需要移除播放器时,我的应用程序崩溃并出现错误
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An instance of AVPlayer cannot remove a time observer that was added by a different instance of AVPlayer.'
播放器的创建方式:
(在单元格中)
-(void)addPlayer {
if (!self.player) {
// This is my custom init method
self.player = [[AVPlayer alloc] initWithFrame:self.container.bounds contentURL:mediaURL];
[self.player setUserInteractionEnabled:YES];
[self.container setUserInteractionEnabled:YES];
[self.container addSubview:self.player];
}
}
如何添加 addTimeObserver:
-(void)beginObservingTime {
// This will monitor the current time of the player
__weak STPlayer *weakSelf = self;
self.observerToken = [self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1.0, NSEC_PER_SEC) queue:nil usingBlock:^ (CMTime time) {
if (CMTimeGetSeconds(time) > self.playbackTime) {
// done buffering
[weakSelf updatePlaybackTime:CMTimeGetSeconds(time)];
[weakSelf.player removeTimeObserver:weakSelf.observerToken];
[weakSelf hideActivityIndicator];
}
}];
}
如何删除播放器:
(在 UITableViewController 中)
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(FeedCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[cell breakDownPlayer];
}
(在单元格中)
-(void)breakDownPlayer {
[self.player breakDown];
}
(在玩家子类中)
-(void)breakDown {
[self.player removeTimeObserver:self.observerToken];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
}
问题:一旦 didEndDisplayingCell
被调用且应用程序未崩溃,如何从 UITableViewCell
中删除播放器?
您是否尝试过在 didEndDisplayingCell 方法中将播放器设置为 nil?
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(FeedCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (cell.player.rate != 0 && (cell.player.error == nil)) {
// player is playing
cell.playButton.hidden = NO;
cell.player = nil;
}
}