多个AVPlayer实例同时暂停导致瞬间但恼人的冻结

时间:2015-04-02 08:14:39

标签: ios objective-c iphone multithreading avplayer

我正在实现一个UICollectionView,它包含多个方形AVPlayerLayers,每行3个,可以填满整个屏幕。所有玩家同时玩。当用户滚动集合视图时,我不得不在每个可重复使用的单元格中重置AVPlayer的URL(因此一次3个)。根据我的观察,重置相当于暂停视频,每次暂停都会阻止主线程上的UI。当重新定义3个可重复使用的单元时,将其阻塞3次意味着非常小的滚动体验。

我也注意到暂停不能完成主要的线程。我在处理内存I / O方面并不是特别明知,但我认为这个故障是由于内存中突然转储了很多东西。所以我想知道是否有任何其他方法来处理这个,所以代码提供了平滑的滚动体验。

2 个答案:

答案 0 :(得分:0)

不,如果在滚动时你没有创建任何玩家对象,滚动会很好,但如果你正在创建玩家对象,那么滚动就会出问题吗?

答案 1 :(得分:0)

您可以使用不同的方法将AVPlayerLayers添加到单元格中,从而找到答案。虽然我今天刚刚完成了这个 - 因此,滚动还不顺利 - 我知道这比将AVPlayer ...代码放在单元子类中更有意义:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = (UICollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:kCellIdentifier forIndexPath:indexPath];

// Enumerate array of visible cells' indexPaths to find a match
if ([self.collectionView.indexPathsForVisibleItems
     indexOfObjectPassingTest:^BOOL(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
         return (obj.item == indexPath.item);
     }]) dispatch_async(dispatch_get_main_queue(), ^{
         [self drawLayerForPlayerForCell:cell atIndexPath:indexPath];
     });


    return cell;
}

- (void)drawPosterFrameForCell:(UICollectionViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    [self.imageManager requestImageForAsset:AppDelegate.sharedAppDelegate.assetsFetchResults[indexPath.item]
                                                          targetSize:AssetGridThumbnailSize
                                                         contentMode:PHImageContentModeAspectFill
                                                             options:nil
                                                       resultHandler:^(UIImage *result, NSDictionary *info) {
                                                           cell.contentView.layer.contents = (__bridge id)result.CGImage;
                                                       }];
}

- (void)drawLayerForPlayerForCell:(UICollectionViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    cell.contentView.layer.sublayers = nil;
    [self.imageManager requestPlayerItemForVideo:(PHAsset *)self.assetsFetchResults[indexPath.item] options:nil resultHandler:^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
        dispatch_sync(dispatch_get_main_queue(), ^{
            if([[info objectForKey:PHImageResultIsInCloudKey] boolValue]) {
                [self drawPosterFrameForCell:cell atIndexPath:indexPath];
            } else {
                AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:[AVPlayer playerWithPlayerItem:playerItem]];
                [playerLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
                [playerLayer setBorderColor:[UIColor whiteColor].CGColor];
                [playerLayer setBorderWidth:1.0f];
                [playerLayer setFrame:cell.contentView.layer.bounds];
                [cell.contentView.layer addSublayer:playerLayer];
                [playerLayer.player play];
            }
        });
    }];
}

请注意,drawPosterFrameForCell方法会将图片放置在无法播放视频的位置,因为它存储在iCloud上,而不是设备上。