Повторное использование AVPlayer в TableView

Может ли кто-нибудь помочь в создании пула AVPlayer для повторного использования в tableView? Итак, идея состоит в том, чтобы иметь пул AVPlayer, скажем, 3, и продолжать повторно использовать их, когда пользователь прокручивает таблицу.

Вот краткий обзор приложения и того, что мы хотим создать:

  • Каждое видео в формате mp4 и длится всего 5 секунд. Таким образом, каждая ячейка будет воспроизводить 5-секундное видео и зацикливать его.
  • Все видео локальные, они будут загружены на диск еще до того, как таблица будет показана пользователю. Это поможет с точки зрения плавной прокрутки tableView.

Прямо сейчас я создаю слишком много AVPlayer и не использую их повторно, что плохо влияет на производительность, например, прокрутка немного прерывистая. Кроме того, Apple не позволяет создавать бесконечное количество AVPlayer.

Любые идеи? Спасибо

Обновление 1:

import UIKit
import VIMVideoPlayer

var cache = NSCache<NSString, VIMVideoPlayerView>()

class FeedTableViewCell: UITableViewCell {
// MARK: - Properties

@IBOutlet weak var containerView: UIView!

static let reuseIdentifier = "FeedTableViewCell"

var video: Video? {
    didSet {
        if let cachedVideoPlayerView = cache.object(forKey: video!.preview!.remoteURL as NSString)  {
            // We have a cached video player view!
            containerView.addSubview(cachedVideoPlayerView)
        } else {
            // There is nothing cached.
            let previewURL = FileManager.applicationDocumentsDirectory.appendingPathComponent(video!.preview!.fileName!)
            let newVideoPlayer = VIMVideoPlayer()
            newVideoPlayer.setURL(previewURL)
            newVideoPlayer.isLooping = true
            newVideoPlayer.isMuted = true
            newVideoPlayer.disableAirplay()

            let newVideoPlayerView = VIMVideoPlayerView()
            newVideoPlayerView.frame = contentView.bounds
            newVideoPlayerView.delegate = self
            newVideoPlayerView.setVideoFillMode(AVLayerVideoGravityResizeAspectFill)
            newVideoPlayerView.player = newVideoPlayer
            containerView.addSubview(newVideoPlayerView)
            cache.setObject(newVideoPlayerView, forKey: video!.preview!.remoteURL as NSString)
        }
    }
}

// MARK: - Life Cycle

override func awakeFromNib() {
    super.awakeFromNib()

    print("AWAKE FROM NIB CELL")
}

override func prepareForReuse() {
    super.prepareForReuse()

}
}

// MARK: - VIMVideoPlayerViewDelegate
extension FeedTableViewCell: VIMVideoPlayerViewDelegate {
func videoPlayerViewIsReady(toPlayVideo videoPlayerView: VIMVideoPlayerView!) {
    videoPlayerView.player.play()
}
}

person JEL    schedule 19.11.2016    source источник
comment
Возможный дубликат AVPlayer.play() в UITableViewCell ненадолго блокирует пользовательский интерфейс   -  person max_    schedule 20.11.2016


Ответы (1)


Расширяя вашу идею использования пула, вместо того, чтобы изобретать велосипед, почему бы не использовать текущую реализацию повторного использования UITableViewCell? В любой момент времени существуют n "многоразовые" UITableViewCell, действующие как ваш пул.

Если каждая из этих ячеек содержит одно подпредставление AVPlayer, тогда управление осуществляется за вас табличным представлением. Поэтому в идентификаторе повторного использования UITableViewCell остановите проигрыватель (при необходимости), обновите его MP4 (в идеале из кеша в памяти) и запустите его снова.

При необходимости вы можете кэшировать положение видео, когда ячейка исчезает, чтобы казалось, что видео никогда не останавливалось во время прокрутки.

-- В качестве примечания, теоретически это будет работать, но не тестировалось с живым приложением. Очевидным предостережением является размер видео, загружаемого в AVPlayer в основном потоке, при попытке поддерживать 60 кадров в секунду.

Редактировать:

Дополнительную информацию см. на странице https://stackoverflow.com/a/35514126/556479.

person max_    schedule 19.11.2016
comment
Пожалуйста, посмотрите мое обновление с некоторым кодом. Судя по вашему ответу, tableView уже создает определенное количество AVPlayer, и мне нужно повторно использовать их, заменив текущий элемент новым элементом - это правильно? Кроме того, в моем текущем коде выше я этого не делаю, кажется, я много раз создаю нового игрока. - person JEL; 20.11.2016
comment
Кстати, VIMVideoPlayerView — это просто оболочка вокруг AVPlayer, это библиотека из Vimeo. - person JEL; 20.11.2016
comment
@JEL точно, вместо того, чтобы создавать новый VIMVideoPlayerView для каждой ячейки, создайте его экземпляр один раз в каждой ячейке и сообщите представлению об остановке в функции prepareForReuse. - person max_; 20.11.2016
comment
@JEL имейте в виду, что ваш код выйдет из строя, если переменная video равна нулю. Вы должны убедиться, что вы занимаетесь этим делом с охранником / если позволите - person max_; 20.11.2016
comment
Хорошо, я думаю, что теперь я начинаю понимать это больше. Что меня все еще смущает, так это возможность повторного использования AVPlayer, потому что я не знаю, как заменить текущее видео новым видео. Где и как производится эта замена? Не могли бы вы объяснить, как это будет сделано, или опубликовать пример кода? Спасибо! - person JEL; 20.11.2016
comment
@JEL Я не уверен, так как не использовал его раньше, но в связанном вопросе используется AVPlayerViewController, и замена выполняется путем обновления свойства player. - person max_; 20.11.2016
comment
Хм, я вижу, к сожалению, вы не можете использовать AVPlayerViewController в ячейке tableView. Это должно быть AVPlayer/AVPlayerLayer. Я застрял на том, как заменить видео новыми - это то, что я каждый раз создавал новый AVPlayer, потому что я не понимал, как заменить видео - person JEL; 20.11.2016
comment
@JEL есть функция под названием replaceCurrentItemWithPlayerItem. stackoverflow.com/questions/33424261/ - person max_; 20.11.2016
comment
Ах, я вижу, я приму ваш ответ. Благодарю вас! Однако, похоже, есть еще одна проблема, которая является отдельным вопросом - как вы заменяете видео без задержек. Ссылка, на которую вы указали выше, имеет ответ, но не принята, поэтому не уверен, что она будет работать. Есть ли у вас какие-либо предложения здесь? - person JEL; 20.11.2016
comment
@JEL Я предлагаю попробовать два метода, описанных в двух связанных вопросах. Кроме этого, я бы попробовал использовать Facebook AsyncDisplayKit и посмотреть, поможет ли это вам. - person max_; 20.11.2016
comment
Спасибо за помощь! Действительно ценю это. Я постараюсь реализовать то, что вы сказали. - person JEL; 20.11.2016
comment
@JEL Я пытаюсь добиться того же, но при смене видео в AVPlayer возникает задержка, нашли ли вы какое-либо решение, кроме AsyncDisplayKit. - person Hassan Khan; 14.05.2020