【问题标题】:Play video on UITableViewCell when it is completely visible完全可见时在 UITableViewCell 上播放视频
【发布时间】:2014-07-18 13:18:31
【问题描述】:

我有一个包含视频 URL 的数组,我想在 UITableviewcell 完全可见时播放这些视频。

我试过了

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView 
{
    NSArray* cells = homeTabl.visibleCells;

    for (HomeCell* cell in cells) 
    {
        if (cell.frame.origin.y > offset.y &&
        cell.frame.origin.y + cell.frame.size.height < offset.y + bounds.size.height)
        {
            NSIndexPath *path = [homeTabl indexPathForCell:cell] ;
            index = path.row;
            fullvisible = YES;
            [homeTabl reloadData];
        }
        else
        {
            fullvisible = NO;
        }
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     if (fullvisible) 
     {
          NSURL *url = [NSURL URLWithString:[[responsearray objectAtIndex:indexPath.row]valueForKey:@"feed_video"]];

          cell.videoItem = [AVPlayerItem playerItemWithURL:url];
          cell.videoPlayer = [AVPlayer playerWithPlayerItem:cell.videoItem];
          cell.avLayer = [AVPlayerLayer playerLayerWithPlayer:cell.videoPlayer];
          cell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
          [cell.videoItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
          [cell.videoItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];

          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil];
          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];

          cell.avLayer.frame = CGRectMake(5, 9, 310, 310);
          [cell.contentView.layer addSublayer:cell.avLayer];
          [cell.videoPlayer play];
          [cell.contentView addSubview:cell.videoActivity];
     }
     else
     {
         cell.videoPlayer = nil;
         [cell.avLayer removeFromSuperlayer];
         cell.videoItem = nil;
         [cell.videoPlayer pause];
     }
}

这很好用 - 但它会拖慢表格视图的滚动速度。 请给我一些其他更好的方法。

【问题讨论】:

  • 什么是videoActivity?
  • @MitulNakum 是活动指示器。

标签: ios objective-c uitableview avplayer


【解决方案1】:

你可以使用

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    isScrolling = NO;
    [homeTabl reloadData];
}

-(void)scrollViewWillBeginDragging:(UIScrollView *)aScrollView
{
    isScrolling = YES;
    [homeTabl reloadData];
    index = -1;
}

在 cellForRowatindexpath 中

if (fullvisible && index == indexPath.row) {
        if (!isScrolling) {

            NSLog(@"video index---%d",indexPath.row);

            if (index == indexPath.row) {
                NSLog(@"video index---%d",indexPath.row);
                cell.videoActivity.hidden = NO;

                // if (index == indexPath.row) {
                NSURL *url = [NSURL URLWithString:[[responsearray objectAtIndex:indexPath.row]valueForKey:@"feed_video"]];

                dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

                dispatch_async(queue, ^{
                    cell.videoItem = [AVPlayerItem playerItemWithURL:url];

                    dispatch_sync(dispatch_get_main_queue(), ^{
                        cell.videoPlayer = [AVPlayer playerWithPlayerItem:cell.videoItem];
                        cell.avLayer = [AVPlayerLayer playerLayerWithPlayer:cell.videoPlayer];
                        cell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
                        [cell.videoItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
                        [cell.videoItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];

                        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil];
                        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];

                        cell.avLayer.frame = CGRectMake(5, 9, 310, 310);
                        [cell.contentView.layer addSublayer:  cell.avLayer];
                        [ cell.videoPlayer play];
                        [cell.contentView addSubview:cell.videoActivity];
                    });
                });
                //                }
                //                else{
                //                    cell.videoActivity.hidden = YES;
                //                    cell.videoPlayer = nil;
                //                    [cell.avLayer removeFromSuperlayer];
                //                    cell.videoItem = nil;
                //                    [cell.videoPlayer pause];
                //                }
            }
        }}

    else{

        cell.videoActivity.hidden = YES;
        cell.videoPlayer = nil;
        [cell.avLayer removeFromSuperlayer];
        cell.videoItem = nil;
        [cell.videoPlayer pause];

    }

【讨论】:

  • @nNthin M Keloth - 这个完全可见的布尔值是什么?
  • @Nitin 这个完全可见的 && 索引是什么?我们在哪里增加索引?
【解决方案2】:

您在主线程中同义地加载视频项目;这意味着在创建表格视图单元格的同时,您的视频项目正在下载并加载到表格视图单元格中。这会导致问题并使滚动非常缓慢和缓慢。要解决此问题,您需要在单独的线程中异步加载视频。

因此,您必须避免同步加载图像,而是异步加载,使用与主线程不同的线程,以便滚动和加载+显示图像可以独立完成,避免任何延迟。

这可能是一个重复的问题,因为它已经被问过并且那里有教程,但是因为我自己在我的第一个 iOS 应用程序上总是遇到这个问题(但对于图片)并且发现它非常混乱,我'我在这里发布答案,希望对您有所帮助。

尝试将与视频加载/显示相关的所有行,尤其是 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath: 中的 playerItemWithURL 移动到单独的块中。还要搜索并阅读其他关于“表格视图单元格中的异步视频加载”的帖子。有很多关于这方面的深入教程和问答。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

dispatch_async(queue, ^{
cell.videoItem = [AVPlayerItem playerItemWithURL:url];

dispatch_sync(dispatch_get_main_queue(), ^{
    cell.videoPlayer = [AVPlayer playerWithPlayerItem:cell.videoItem];
        cell.avLayer = [AVPlayerLayer playerLayerWithPlayer:cell.videoPlayer];
        cell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
        [cell.videoItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
        [cell.videoItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];

         cell.avLayer.frame = CGRectMake(5, 9, 310, 310);
         [cell.contentView.layer addSublayer:  cell.avLayer];
         [ cell.videoPlayer play];
         [cell.contentView addSubview:cell.videoActivity];
    });
});

【讨论】:

  • 您是否介意分享一下您如何处理删除视图控制器作为 cell.VideoItem 的观察者,用于播放BufferEmpty 和playbackLikelyToKeepUp?
  • 这很有帮助!感谢您发布此代码:)
  • 嘿如何播放可见单元格中心的tableview的单个视频?你能帮我吗?
  • @Anita 我不是男人,但不客气,很高兴它对您有所帮助。 :)
  • 对不起 Neeku.. 我没看到名字... :P
【解决方案3】:

避免每次播放视频时都重新加载表格视图。您可以在可见单元格上执行视频播放代码,而无需重新加载整个 tableview。

另外,我怀疑您真的不想在表格视图停止滚动之前播放视频。请参阅How to detect when a UIScrollView has finished scrolling(检测UIScrollView 何时完成滚动非常不直观)。

如果您确实想在滚动视图停止滚动之前开始播放视频,至少修改您的代码以检查可见单元格是否已经在播放,然后什么也不做。现在,只要一个单元格完全可见,播放视频的tableView:cellForRowAtIndexPath: 代码就会执行很多次(我怀疑这种情况经常发生!)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 2020-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多