Я пытаюсь создать приложение, похожее на Vine, где это просто поток ячеек, а видео воспроизводится автоматически, когда вы прокручиваете и останавливаетесь на ячейке.
У каждого UICollectionViewCell
есть свой AVPlayer
.
Прямо сейчас моя текущая настройка по большей части работает нормально, но после прокрутки некоторое время приложение в конечном итоге падает, и мой аналитический SDK показывает, что сбой вызван следующей ошибкой:
An AVPlayerItem cannot be associated with more than one instance of AVPlayer
Приложение также иногда падает сразу после того, как я получаю предупреждение о памяти в консоли.
У меня есть ощущение, что это связано с тем, как я настраиваю AVPlayers
для каждого UICollectionViewCell
, и как повторно используются ячейки, но я не совсем уверен.
Вот код, который у меня есть в моем контроллере представления, который касается настройки ячеек и их AVPlayers
:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCollectionViewCellSubclass *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
[cell load:self.objectsFromServer[indexPath.row] withBannerColor:self.bannerColors[indexPath.row % self.bannerColors.count]];
QBCOCustomObject *objectFromServer = self.objectsFromServer[indexPath.row];
NSURL *videoURL = [NSURL URLWithString:objectFromServer.fields[@"Video_URL"]];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
cell.playerItem = [AVPlayerItem playerItemWithURL:videoURL];
dispatch_sync(dispatch_get_main_queue(), ^{
cell.player = [AVPlayer playerWithPlayerItem:cell.playerItem];
cell.playerLayer = [AVPlayerLayer playerLayerWithPlayer:cell.player];
cell.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
cell.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
cell.playerLayer.frame = CGRectMake(0, 0, 320, 186.5);
[cell.banner.layer addSublayer:cell.playerLayer];
});
});
}
return cell;
}
Я использую scrollViewDidScroll:
для воспроизведения/приостановки ячеек. Я проверяю, чтобы убедиться, что текущая видимая ячейка не является последней ячейкой lastPlayingCell/той, которая воспроизводит видео, и если это не так, то я приостанавливаю lastPlayingCell и воспроизводю видео видимой ячейки.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// Play/Pause Video
CGRect visibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];
NSLog(@"%@",visibleIndexPath);
MyCollectionViewCellSubclass *cell = (MyCollectionViewCellSubclass *)[self.collectionView cellForItemAtIndexPath:visibleIndexPath];
if (cell != self.lastPlayingCell) {
[self.lastPlayingCell pauseVideo];
self.lastPlayingCell = cell;
[cell playVideo];
}
}