A ViewController
has a UICollectionView
. One of the cells contains JWVideoView
. The app is frequently crashing on prepareForReuse
in this cell.
There is no valuable info in the log. So I am having trouble figuring out the reason for the crash.
I've created a project example that demonstrates the crash. You can find it https://github.com/fuxlud/JWExample
If the link between the cell
and the videoView
is removed, the crash will not happen.
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() {
}
}
pod 'JWPlayer-SDK', '2.8.6'
. In addition, I've updated my question with more relevant code. If you prefer we can talk over email. – Arouse