在UITableViewCell完全可见时播放视频

时间:2014-07-18 13:18:31

标签: ios objective-c uitableview avplayer

我有一个包含视频网址的数组,我想在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];
     }
}

这样可以正常工作 - 但可怕的是减缓了表格视图的滚动速度。 请建议我一些其他更好的方法。

3 个答案:

答案 0 :(得分:9)

您可以使用

-(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];

    }

答案 1 :(得分:8)

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

因此,您必须避免同步加载图像,而是异步加载图像,使用主线程以外的其他线程,以便滚动和加载+显示图像可以依赖地完成,避免任何类型的延迟。

这可能是一个重复的问题,因为它已经被问过并且有教程,但是因为我自己总是在我的第一个iOS应用程序上遇到此问题(但是对于图片)并且发现它非常令人困惑的是,我在这里发布了答案,希望它有用。

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

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];
    });
});

答案 2 :(得分:1)

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

另外,我怀疑在桌面视图停止滚动之前,你真的不想播放视频。请参阅How to detect when a UIScrollView has finished scrolling(检测UIScrollView完成滚动的时间出乎意料地不直观)。

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