fix: fix the kvo compliance crash when rapidly switching source
This commit is contained in:
parent
a2cdf0f656
commit
1f27ffbc81
@ -233,102 +233,92 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Player and source
|
// MARK: - Player and source
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
func setSrc(_ source:NSDictionary!) {
|
func setSrc(_ source:NSDictionary!) {
|
||||||
_source = VideoSource(source)
|
DispatchQueue.global(qos: .default).async {
|
||||||
if (_source?.uri == nil || _source?.uri == "") {
|
_source = VideoSource(source)
|
||||||
DispatchQueue.global(qos: .default).async {
|
if (_source?.uri == nil || _source?.uri == "") {
|
||||||
self._player?.replaceCurrentItem(with: nil)
|
self._player?.replaceCurrentItem(with: nil)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
removePlayerLayer()
|
||||||
}
|
_playerObserver.player = nil
|
||||||
removePlayerLayer()
|
_playerObserver.playerItem = nil
|
||||||
_playerObserver.player = nil
|
|
||||||
_playerObserver.playerItem = nil
|
|
||||||
|
|
||||||
// perform on next run loop, otherwise other passed react-props may not be set
|
// perform on next run loop, otherwise other passed react-props may not be set
|
||||||
RCTVideoUtils.delay()
|
RCTVideoUtils.delay()
|
||||||
.then{ [weak self] in
|
.then{ [weak self] in
|
||||||
guard let self = self else {throw NSError(domain: "", code: 0, userInfo: nil)}
|
guard let self = self else {throw NSError(domain: "", code: 0, userInfo: nil)}
|
||||||
guard let source = self._source else {
|
guard let source = self._source else {
|
||||||
DebugLog("The source not exist")
|
DebugLog("The source not exist")
|
||||||
throw NSError(domain: "", code: 0, userInfo: nil)
|
throw NSError(domain: "", code: 0, userInfo: nil)
|
||||||
}
|
}
|
||||||
if let uri = source.uri, uri.starts(with: "ph://") {
|
if let uri = source.uri, uri.starts(with: "ph://") {
|
||||||
return Promise {
|
return Promise {
|
||||||
RCTVideoUtils.preparePHAsset(uri: uri).then { asset in
|
RCTVideoUtils.preparePHAsset(uri: uri).then { asset in
|
||||||
return self.playerItemPrepareText(asset:asset, assetOptions:nil)
|
return self.playerItemPrepareText(asset:asset, assetOptions:nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
guard let assetResult = RCTVideoUtils.prepareAsset(source: source),
|
||||||
guard let assetResult = RCTVideoUtils.prepareAsset(source: source),
|
let asset = assetResult.asset,
|
||||||
let asset = assetResult.asset,
|
let assetOptions = assetResult.assetOptions else {
|
||||||
let assetOptions = assetResult.assetOptions else {
|
DebugLog("Could not find video URL in source '\(self._source)'")
|
||||||
DebugLog("Could not find video URL in source '\(self._source)'")
|
throw NSError(domain: "", code: 0, userInfo: nil)
|
||||||
throw NSError(domain: "", code: 0, userInfo: nil)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if canImport(RCTVideoCache)
|
#if canImport(RCTVideoCache)
|
||||||
if self._videoCache.shouldCache(source:source, textTracks:self._textTracks) {
|
if self._videoCache.shouldCache(source:source, textTracks:self._textTracks) {
|
||||||
return self._videoCache.playerItemForSourceUsingCache(uri: source.uri, assetOptions:assetOptions)
|
return self._videoCache.playerItemForSourceUsingCache(uri: source.uri, assetOptions:assetOptions)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if self._drm != nil || self._localSourceEncryptionKeyScheme != nil {
|
if self._drm != nil || self._localSourceEncryptionKeyScheme != nil {
|
||||||
self._resouceLoaderDelegate = RCTResourceLoaderDelegate(
|
self._resouceLoaderDelegate = RCTResourceLoaderDelegate(
|
||||||
asset: asset,
|
asset: asset,
|
||||||
drm: self._drm,
|
drm: self._drm,
|
||||||
localSourceEncryptionKeyScheme: self._localSourceEncryptionKeyScheme,
|
localSourceEncryptionKeyScheme: self._localSourceEncryptionKeyScheme,
|
||||||
onVideoError: self.onVideoError,
|
onVideoError: self.onVideoError,
|
||||||
onGetLicense: self.onGetLicense,
|
onGetLicense: self.onGetLicense,
|
||||||
reactTag: self.reactTag
|
reactTag: self.reactTag
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return Promise{self.playerItemPrepareText(asset: asset, assetOptions:assetOptions)}
|
return Promise{self.playerItemPrepareText(asset: asset, assetOptions:assetOptions)}
|
||||||
}.then{[weak self] (playerItem:AVPlayerItem!) in
|
}.then{[weak self] (playerItem:AVPlayerItem!) in
|
||||||
guard let self = self else {throw NSError(domain: "", code: 0, userInfo: nil)}
|
guard let self = self else {throw NSError(domain: "", code: 0, userInfo: nil)}
|
||||||
|
|
||||||
self._player?.pause()
|
self._player?.pause()
|
||||||
self._playerItem = playerItem
|
self._playerItem = playerItem
|
||||||
self._playerObserver.playerItem = self._playerItem
|
self._playerObserver.playerItem = self._playerItem
|
||||||
self.setPreferredForwardBufferDuration(self._preferredForwardBufferDuration)
|
self.setPreferredForwardBufferDuration(self._preferredForwardBufferDuration)
|
||||||
self.setFilter(self._filterName)
|
self.setFilter(self._filterName)
|
||||||
if let maxBitRate = self._maxBitRate {
|
if let maxBitRate = self._maxBitRate {
|
||||||
self._playerItem?.preferredPeakBitRate = Double(maxBitRate)
|
self._playerItem?.preferredPeakBitRate = Double(maxBitRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
self._player = self._player ?? AVPlayer()
|
self._player = self._player ?? AVPlayer()
|
||||||
DispatchQueue.global(qos: .default).async {
|
self._player.replaceCurrentItem(with: playerItem)
|
||||||
self._player?.replaceCurrentItem(with: playerItem)
|
self._playerObserver.player = self._player
|
||||||
}
|
self.applyModifiers()
|
||||||
self._playerObserver.player = self._player
|
self._player?.actionAtItemEnd = .none
|
||||||
self.applyModifiers()
|
|
||||||
self._player?.actionAtItemEnd = .none
|
|
||||||
|
|
||||||
if #available(iOS 10.0, *) {
|
if #available(iOS 10.0, *) {
|
||||||
self.setAutomaticallyWaitsToMinimizeStalling(self._automaticallyWaitsToMinimizeStalling)
|
self.setAutomaticallyWaitsToMinimizeStalling(self._automaticallyWaitsToMinimizeStalling)
|
||||||
}
|
}
|
||||||
|
|
||||||
if self._adTagUrl != nil {
|
//Perform on next run loop, otherwise onVideoLoadStart is nil
|
||||||
// Set up your content playhead and contentComplete callback.
|
self.onVideoLoadStart?([
|
||||||
self._contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: self._player!)
|
"src": [
|
||||||
|
"uri": self._source?.uri ?? NSNull(),
|
||||||
self._imaAdsManager.setUpAdsLoader()
|
"type": self._source?.type ?? NSNull(),
|
||||||
}
|
"isNetwork": NSNumber(value: self._source?.isNetwork ?? false)
|
||||||
|
],
|
||||||
//Perform on next run loop, otherwise onVideoLoadStart is nil
|
"drm": self._drm?.json ?? NSNull(),
|
||||||
self.onVideoLoadStart?([
|
"target": self.reactTag
|
||||||
"src": [
|
])
|
||||||
"uri": self._source?.uri ?? NSNull(),
|
}.catch{_ in }
|
||||||
"type": self._source?.type ?? NSNull(),
|
_videoLoadStarted = true
|
||||||
"isNetwork": NSNumber(value: self._source?.isNetwork ?? false)
|
}
|
||||||
],
|
|
||||||
"drm": self._drm?.json ?? NSNull(),
|
|
||||||
"target": self.reactTag
|
|
||||||
])
|
|
||||||
}.catch{_ in }
|
|
||||||
_videoLoadStarted = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
|
Loading…
Reference in New Issue
Block a user