У 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() {
}
}
Спасибо, @iMHiteshSurani, за поучительный и грустный комментарий.
Жаль это слышать @Luda. Знаете ли вы, какую версию SDK вы используете? За последние пару месяцев мы внесли значительные улучшения в наши SDK.
@ksindi, о боже! Вице-президент по инженерным разработкам в JW Player! Потрясающе для того, чтобы реагировать на StackOverflow. В настоящее время мы используем pod 'JWPlayer-SDK', '2.8.6'. Кроме того, я обновил свой вопрос более подходящим кодом. Если хотите, мы можем поговорить по электронной почте.
@Luda заметила, что версия, которую вы используете, <3x. С тех пор мы значительно улучшили стабильность и больше не поддерживаем 2x. Можно ли будет перейти на более позднюю версию? Как это сделать, см. developer.jwplayer.com/sdk/ios/docs/developer-guide/migration/…. Наш API намного удобнее для Swift.
@ksindi я обновлю
@ksindi К сожалению, приложение все еще падает.
@Luda Будет ли приложение по-прежнему падать, если вы удалите JWVideoView из ячейки?
не могли бы вы поделиться журналом ошибок, пожалуйста, даже если он кажется вам бесценным?
@arturdev Я создал пример проекта, демонстрирующий сбой. Можно найти github.com/fuxlud/JWExample Если связь между ячейкой и видеоВью убрать, краша не будет.
@ugur Я создал пример проекта, демонстрирующий сбой. Можно найти github.com/fuxlud/JWExample Если связь между ячейкой и видеоВью убрать, краша не будет.
@ksindi Я создал пример проекта, демонстрирующий сбой. Можно найти github.com/fuxlud/JWExample Если связь между ячейкой и видеоВью убрать, краша не будет.





Основываясь на вашем примере проекта, вы увидели следующую проблему внутри вашего класса 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
}
}
Когда я работал с JWPlayer, я столкнулся со многими проблемами или сбоями. Поверьте мне, это не связано с нашим программированием, потому что у JWPlayer так много известных проблем. Я думаю, вам нужно поговорить со службой поддержки по поводу проблемы. В моем приложении было 20 тысяч сбоев, связанных с JWPlayer, это больше, чем общее количество пользователей. Если вы прокомментировали код, связанный с JWPlayer, то все работало, как и ожидалось.