Сбой на UICollectionViewCell с JWVideoView - Swift

У ViewController есть UICollectionView. Одна из ячеек содержит JWVideoView. Приложение часто падает на prepareForReuse в этой ячейке.

В журнале нет ценной информации. Поэтому у меня возникли проблемы с выяснением причины сбоя.

Я создал пример проекта, демонстрирующий сбой. Вы можете найти его https://github.com/fuxlud/JWExample Если связь между cell и videoView удалить, сбоя не произойдет.

import UIKit

class VideoArticleElementCollectionViewCell: UICollectionViewCell {

    // MARK: - Properties

    public var imageURL: String? { didSet { videoView?.imageURL = imageURL } }
    public var videoId: String? { didSet { videoView?.videoId = videoId } }

    @IBOutlet private var videoView: JWVideoView?

    // MARK: - Reuse

    override func prepareForReuse() {
        super.prepareForReuse() // Crashing here! (Thread 1: EXC_BAD_ACCESS (code=1, address=0x7e8))

        videoView?.stopPlayingVideo()
    }

    deinit {

        videoView?.stopPlayingVideo()
    }
}








import UIKit

class JWVideoView: UIView, JWPlayerDelegate {

    // MARK: Properties

    public var imageURL: String?
    public var videoId: String? { didSet { setupPlayer() } }

    private var jwPlayer: JWPlayerController?
    private let jwPlayerURL = "https://content.jwplatform.com/manifests/"
    private var didPause = false

    // MARK: - Initialization

    override init(frame: CGRect) {

        super.init(frame: frame)
        setup()
    }

    convenience init() {

        self.init(frame: CGRect.zero)
    }

    required init?(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)
        setup()
    }

    // MARK: - Setup

    private func setup() {}

    private func setupPlayer() {



            guard let videoId = self.videoId else { return }

            let playerURL = jwPlayerURL + videoId + ".m3u8"

            let configuration: JWConfig = JWConfig(contentURL: playerURL)
            configuration.controls = true
            configuration.autostart = true
//            configuration.premiumSkin = JWPremiumSkinGlow
            configuration.image = imageURL

            jwPlayer = JWPlayerController(config: configuration)

            if let player = jwPlayer {

                player.forceFullScreenOnLandscape = true
                player.forceLandscapeOnFullScreen = true
                player.view?.autoresizingMask = [.flexibleHeight, .flexibleWidth]
                player.view?.frame = bounds
                player.delegate = self
                player.volume = 0.0
                if let view = player.view { addSubview(view) }
            }

    }

    // MARK: - Orientation

    private func enableAllOrientation(enable: Bool) {

        if let delegate = UIApplication.shared.delegate as? AppDelegate {

//            delegate.shouldEnableLandscape = enable
        }
    }

    // MARK: API

    public func stopPlayingVideo() {

        enableAllOrientation(enable: false)

        if jwPlayer != nil {

            jwPlayer!.stop()
        }
    }

    // MARK: - JWPlayerDelegate

    internal func onFullscreen(_ status: Bool) {

        if status == false {

            let value = UIInterfaceOrientation.portrait.rawValue
            UIDevice.current.setValue(value, forKey: "orientation")
        }
    }

    internal func onPlayAttempt() {

        if jwPlayer != nil {

            enableAllOrientation(enable: true)


        }
    }

    internal func onPlay(_ oldValue: String) {

        if didPause {

            didPause = false
        }
    }

    internal func onPause(_ oldValue: String) {

        didPause = true

    }

    internal func onComplete() {

    }

}

Когда я работал с JWPlayer, я столкнулся со многими проблемами или сбоями. Поверьте мне, это не связано с нашим программированием, потому что у JWPlayer так много известных проблем. Я думаю, вам нужно поговорить со службой поддержки по поводу проблемы. В моем приложении было 20 тысяч сбоев, связанных с JWPlayer, это больше, чем общее количество пользователей. Если вы прокомментировали код, связанный с JWPlayer, то все работало, как и ожидалось.

Hitesh Surani 28.07.2019 10:04

Спасибо, @iMHiteshSurani, за поучительный и грустный комментарий.

Luda 28.07.2019 10:24

Жаль это слышать @Luda. Знаете ли вы, какую версию SDK вы используете? За последние пару месяцев мы внесли значительные улучшения в наши SDK.

Kamil Sindi 29.07.2019 15:48

@ksindi, о боже! Вице-президент по инженерным разработкам в JW Player! Потрясающе для того, чтобы реагировать на StackOverflow. В настоящее время мы используем pod 'JWPlayer-SDK', '2.8.6'. Кроме того, я обновил свой вопрос более подходящим кодом. Если хотите, мы можем поговорить по электронной почте.

Luda 30.07.2019 09:52

@Luda заметила, что версия, которую вы используете, <3x. С тех пор мы значительно улучшили стабильность и больше не поддерживаем 2x. Можно ли будет перейти на более позднюю версию? Как это сделать, см. developer.jwplayer.com/sdk/ios/docs/developer-guide/migratio‌​n/…. Наш API намного удобнее для Swift.

Kamil Sindi 30.07.2019 16:26

@ksindi я обновлю

Luda 31.07.2019 08:29

@ksindi К сожалению, приложение все еще падает.

Luda 31.07.2019 10:10

@Luda Будет ли приложение по-прежнему падать, если вы удалите JWVideoView из ячейки?

arturdev 02.08.2019 09:34

не могли бы вы поделиться журналом ошибок, пожалуйста, даже если он кажется вам бесценным?

ugur 05.08.2019 00:40

@arturdev Я создал пример проекта, демонстрирующий сбой. Можно найти github.com/fuxlud/JWExample Если связь между ячейкой и видеоВью убрать, краша не будет.

Luda 05.08.2019 13:16

@ugur Я создал пример проекта, демонстрирующий сбой. Можно найти github.com/fuxlud/JWExample Если связь между ячейкой и видеоВью убрать, краша не будет.

Luda 05.08.2019 13:16

@ksindi Я создал пример проекта, демонстрирующий сбой. Можно найти github.com/fuxlud/JWExample Если связь между ячейкой и видеоВью убрать, краша не будет.

Luda 05.08.2019 13:17
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
12
388
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Основываясь на вашем примере проекта, вы увидели следующую проблему внутри вашего класса JWVideoView: каждый раз, когда вы устанавливаете свойство videoId, он снова инициализирует jwPlayer, а также снова считывает это представление в стек.

1. Решение (удалите playerView и установите плеер на ноль):

  private func setupPlayer() {

  jwPlayer?.view?.removeFromSuperview()
  jwPlayer = nil

  guard let videoId = self.videoId else { return }

  let playerURL = jwPlayerURL + videoId + ".m3u8"

  let configuration: JWConfig = JWConfig(contentURL: playerURL)
  configuration.controls = true
  configuration.autostart = true
  configuration.image = imageURL

  jwPlayer = JWPlayerController(config: configuration)
  jwPlayer?.forceFullScreenOnLandscape = true
  jwPlayer?.forceLandscapeOnFullScreen = true
  jwPlayer?.view?.autoresizingMask = [.flexibleHeight, .flexibleWidth]
  jwPlayer?.view?.frame = bounds
  jwPlayer?.delegate = self
  jwPlayer?.volume = 0.0

  if let view = jwPlayer?.view {
      addSubview(view)
  }

}

2. Решение (оставить плеер и экземпляр вида и сбросить настройки плеера)

  private func setupPlayer() {

  guard let videoId = self.videoId else { return }

  let playerURL = jwPlayerURL + videoId + ".m3u8"

  let configuration: JWConfig = JWConfig(contentURL: playerURL)
  configuration.controls = true
  configuration.autostart = true
  configuration.image = imageURL

  if jwPlayer == nil {

      jwPlayer = JWPlayerController(config: configuration)
      jwPlayer?.forceFullScreenOnLandscape = true
      jwPlayer?.forceLandscapeOnFullScreen = true
      jwPlayer?.view?.autoresizingMask = [.flexibleHeight, .flexibleWidth]
      jwPlayer?.view?.frame = bounds
      jwPlayer?.delegate = self
      jwPlayer?.volume = 0.0

      if let view = jwPlayer?.view {
          addSubview(view)
      }
  }else{
    //reset the configuration of the player here. but i dont now how this is possible with jwPlayer
  }

}

Другие вопросы по теме