Merge pull request #3167 from BeApp/feature/ios-fix
#3166 Memory leaks #3085 onFullscreen call backs are never fired #3040 [Bug] Fullscreen broken on iOS due to #3017
This commit is contained in:
commit
9914faf4d9
@ -4,7 +4,7 @@ import GoogleInteractiveMediaAds
|
|||||||
|
|
||||||
class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
||||||
|
|
||||||
private var _video:RCTVideo
|
private weak var _video: RCTVideo?
|
||||||
|
|
||||||
/* Entry point for the SDK. Used to make ad requests. */
|
/* Entry point for the SDK. Used to make ad requests. */
|
||||||
private var adsLoader: IMAAdsLoader!
|
private var adsLoader: IMAAdsLoader!
|
||||||
@ -23,6 +23,7 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func requestAds() {
|
func requestAds() {
|
||||||
|
guard let _video = _video else {return}
|
||||||
// Create ad display container for ad rendering.
|
// Create ad display container for ad rendering.
|
||||||
let adDisplayContainer = IMAAdDisplayContainer(adContainer: _video, viewController: _video.reactViewController())
|
let adDisplayContainer = IMAAdDisplayContainer(adContainer: _video, viewController: _video.reactViewController())
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
|||||||
// MARK: - IMAAdsLoaderDelegate
|
// MARK: - IMAAdsLoaderDelegate
|
||||||
|
|
||||||
func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
|
func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
|
||||||
|
guard let _video = _video else {return}
|
||||||
// Grab the instance of the IMAAdsManager and set yourself as the delegate.
|
// Grab the instance of the IMAAdsManager and set yourself as the delegate.
|
||||||
adsManager = adsLoadedData.adsManager
|
adsManager = adsLoadedData.adsManager
|
||||||
adsManager?.delegate = self
|
adsManager?.delegate = self
|
||||||
@ -71,12 +73,13 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
|||||||
print("Error loading ads: " + adErrorData.adError.message!)
|
print("Error loading ads: " + adErrorData.adError.message!)
|
||||||
}
|
}
|
||||||
|
|
||||||
_video.setPaused(false)
|
_video?.setPaused(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - IMAAdsManagerDelegate
|
// MARK: - IMAAdsManagerDelegate
|
||||||
|
|
||||||
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
|
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
|
||||||
|
guard let _video = _video else {return}
|
||||||
// Mute ad if the main player is muted
|
// Mute ad if the main player is muted
|
||||||
if (_video.isMuted()) {
|
if (_video.isMuted()) {
|
||||||
adsManager.volume = 0;
|
adsManager.volume = 0;
|
||||||
@ -102,19 +105,19 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to playing content
|
// Fall back to playing content
|
||||||
_video.setPaused(false)
|
_video?.setPaused(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
|
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
|
||||||
// Pause the content for the SDK to play ads.
|
// Pause the content for the SDK to play ads.
|
||||||
_video.setPaused(true)
|
_video?.setPaused(true)
|
||||||
_video.setAdPlaying(true)
|
_video?.setAdPlaying(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
|
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
|
||||||
// Resume the content since the SDK is done playing ads (at least for now).
|
// Resume the content since the SDK is done playing ads (at least for now).
|
||||||
_video.setAdPlaying(false)
|
_video?.setAdPlaying(false)
|
||||||
_video.setPaused(false)
|
_video?.setPaused(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Helpers
|
// MARK: - Helpers
|
||||||
|
@ -25,7 +25,7 @@ protocol RCTPlayerObserverHandler: RCTPlayerObserverHandlerObjc {
|
|||||||
|
|
||||||
class RCTPlayerObserver: NSObject {
|
class RCTPlayerObserver: NSObject {
|
||||||
|
|
||||||
var _handlers: RCTPlayerObserverHandler!
|
weak var _handlers: RCTPlayerObserverHandler?
|
||||||
|
|
||||||
var player:AVPlayer? {
|
var player:AVPlayer? {
|
||||||
willSet {
|
willSet {
|
||||||
@ -84,11 +84,13 @@ class RCTPlayerObserver: NSObject {
|
|||||||
private var _playerViewControllerOverlayFrameObserver:NSKeyValueObservation?
|
private var _playerViewControllerOverlayFrameObserver:NSKeyValueObservation?
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
NotificationCenter.default.removeObserver(_handlers)
|
if let _handlers = _handlers {
|
||||||
|
NotificationCenter.default.removeObserver(_handlers)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addPlayerObservers() {
|
func addPlayerObservers() {
|
||||||
guard let player = player else {
|
guard let player = player, let _handlers = _handlers else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +104,7 @@ class RCTPlayerObserver: NSObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addPlayerItemObservers() {
|
func addPlayerItemObservers() {
|
||||||
guard let playerItem = playerItem else { return }
|
guard let playerItem = playerItem, let _handlers = _handlers else { return }
|
||||||
|
|
||||||
_playerItemStatusObserver = playerItem.observe(\.status, options: [.new, .old], changeHandler: _handlers.handlePlayerItemStatusChange)
|
_playerItemStatusObserver = playerItem.observe(\.status, options: [.new, .old], changeHandler: _handlers.handlePlayerItemStatusChange)
|
||||||
_playerPlaybackBufferEmptyObserver = playerItem.observe(\.isPlaybackBufferEmpty, options: [.new, .old], changeHandler: _handlers.handlePlaybackBufferKeyEmpty)
|
_playerPlaybackBufferEmptyObserver = playerItem.observe(\.isPlaybackBufferEmpty, options: [.new, .old], changeHandler: _handlers.handlePlaybackBufferKeyEmpty)
|
||||||
@ -118,7 +120,7 @@ class RCTPlayerObserver: NSObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addPlayerViewControllerObservers() {
|
func addPlayerViewControllerObservers() {
|
||||||
guard let playerViewController = playerViewController else { return }
|
guard let playerViewController = playerViewController, let _handlers = _handlers else { return }
|
||||||
|
|
||||||
_playerViewControllerReadyForDisplayObserver = playerViewController.observe(\.isReadyForDisplay, options: [.new], changeHandler: _handlers.handleReadyForDisplay)
|
_playerViewControllerReadyForDisplayObserver = playerViewController.observe(\.isReadyForDisplay, options: [.new], changeHandler: _handlers.handleReadyForDisplay)
|
||||||
|
|
||||||
@ -131,6 +133,7 @@ class RCTPlayerObserver: NSObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addPlayerLayerObserver() {
|
func addPlayerLayerObserver() {
|
||||||
|
guard let _handlers = _handlers else {return}
|
||||||
_playerLayerReadyForDisplayObserver = playerLayer?.observe(\.isReadyForDisplay, options: [.new], changeHandler: _handlers.handleReadyForDisplay)
|
_playerLayerReadyForDisplayObserver = playerLayer?.observe(\.isReadyForDisplay, options: [.new], changeHandler: _handlers.handleReadyForDisplay)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +142,7 @@ class RCTPlayerObserver: NSObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addPlayerTimeObserver() {
|
func addPlayerTimeObserver() {
|
||||||
|
guard let _handlers = _handlers else {return}
|
||||||
removePlayerTimeObserver()
|
removePlayerTimeObserver()
|
||||||
let progressUpdateIntervalMS:Float64 = _progressUpdateInterval / 1000
|
let progressUpdateIntervalMS:Float64 = _progressUpdateInterval / 1000
|
||||||
// @see endScrubbing in AVPlayerDemoPlaybackViewController.m
|
// @see endScrubbing in AVPlayerDemoPlaybackViewController.m
|
||||||
@ -174,6 +178,7 @@ class RCTPlayerObserver: NSObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func attachPlayerEventListeners() {
|
func attachPlayerEventListeners() {
|
||||||
|
guard let _handlers = _handlers else {return}
|
||||||
|
|
||||||
NotificationCenter.default.removeObserver(_handlers,
|
NotificationCenter.default.removeObserver(_handlers,
|
||||||
name:NSNotification.Name.AVPlayerItemDidPlayToEndTime,
|
name:NSNotification.Name.AVPlayerItemDidPlayToEndTime,
|
||||||
@ -202,6 +207,8 @@ class RCTPlayerObserver: NSObject {
|
|||||||
func clearPlayer() {
|
func clearPlayer() {
|
||||||
player = nil
|
player = nil
|
||||||
playerItem = nil
|
playerItem = nil
|
||||||
NotificationCenter.default.removeObserver(_handlers)
|
if let _handlers = _handlers {
|
||||||
|
NotificationCenter.default.removeObserver(_handlers)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
private var _fullscreenAutorotate:Bool = true
|
private var _fullscreenAutorotate:Bool = true
|
||||||
private var _fullscreenOrientation:String! = "all"
|
private var _fullscreenOrientation:String! = "all"
|
||||||
private var _fullscreenPlayerPresented:Bool = false
|
private var _fullscreenPlayerPresented:Bool = false
|
||||||
|
private var _fullscreenUncontrolPlayerPresented:Bool = false // to call events switching full screen mode from player controls
|
||||||
private var _filterName:String!
|
private var _filterName:String!
|
||||||
private var _filterEnabled:Bool = false
|
private var _filterEnabled:Bool = false
|
||||||
private var _presentingViewController:UIViewController?
|
private var _presentingViewController:UIViewController?
|
||||||
@ -246,7 +247,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
// MARK: - Player and source
|
// MARK: - Player and source
|
||||||
@objc
|
@objc
|
||||||
func setSrc(_ source:NSDictionary!) {
|
func setSrc(_ source:NSDictionary!) {
|
||||||
DispatchQueue.global(qos: .default).async {
|
DispatchQueue.global(qos: .default).async { [weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
self._source = VideoSource(source)
|
self._source = VideoSource(source)
|
||||||
if (self._source?.uri == nil || self._source?.uri == "") {
|
if (self._source?.uri == nil || self._source?.uri == "") {
|
||||||
self._player?.replaceCurrentItem(with: nil)
|
self._player?.replaceCurrentItem(with: nil)
|
||||||
@ -662,7 +664,13 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
self.onVideoFullscreenPlayerWillPresent?(["target": reactTag as Any])
|
self.onVideoFullscreenPlayerWillPresent?(["target": reactTag as Any])
|
||||||
|
|
||||||
if let playerViewController = _playerViewController {
|
if let playerViewController = _playerViewController {
|
||||||
viewController.present(playerViewController, animated:true, completion:{
|
if(_controls) {
|
||||||
|
// prevents crash https://github.com/react-native-video/react-native-video/issues/3040
|
||||||
|
self._playerViewController?.removeFromParent()
|
||||||
|
}
|
||||||
|
|
||||||
|
viewController.present(playerViewController, animated:true, completion:{ [weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
self._playerViewController?.showsPlaybackControls = self._controls
|
self._playerViewController?.showsPlaybackControls = self._controls
|
||||||
self._fullscreenPlayerPresented = fullscreen
|
self._fullscreenPlayerPresented = fullscreen
|
||||||
self._playerViewController?.autorotate = self._fullscreenAutorotate
|
self._playerViewController?.autorotate = self._fullscreenAutorotate
|
||||||
@ -674,8 +682,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
}
|
}
|
||||||
} else if !fullscreen && _fullscreenPlayerPresented, let _playerViewController = _playerViewController {
|
} else if !fullscreen && _fullscreenPlayerPresented, let _playerViewController = _playerViewController {
|
||||||
self.videoPlayerViewControllerWillDismiss(playerViewController: _playerViewController)
|
self.videoPlayerViewControllerWillDismiss(playerViewController: _playerViewController)
|
||||||
_presentingViewController?.dismiss(animated: true, completion:{
|
_presentingViewController?.dismiss(animated: true, completion:{[weak self] in
|
||||||
self.videoPlayerViewControllerDidDismiss(playerViewController: _playerViewController)
|
self?.videoPlayerViewControllerDidDismiss(playerViewController: _playerViewController)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1103,12 +1111,27 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
let oldRect = change.oldValue
|
let oldRect = change.oldValue
|
||||||
let newRect = change.newValue
|
let newRect = change.newValue
|
||||||
if !oldRect!.equalTo(newRect!) {
|
if !oldRect!.equalTo(newRect!) {
|
||||||
|
// https://github.com/react-native-video/react-native-video/issues/3085#issuecomment-1557293391
|
||||||
if newRect!.equalTo(UIScreen.main.bounds) {
|
if newRect!.equalTo(UIScreen.main.bounds) {
|
||||||
RCTLog("in fullscreen")
|
RCTLog("in fullscreen")
|
||||||
|
if (!_fullscreenUncontrolPlayerPresented) {
|
||||||
|
_fullscreenUncontrolPlayerPresented = true;
|
||||||
|
|
||||||
self.reactViewController().view.frame = UIScreen.main.bounds
|
self.onVideoFullscreenPlayerWillPresent?(["target": self.reactTag as Any])
|
||||||
self.reactViewController().view.setNeedsLayout()
|
self.onVideoFullscreenPlayerDidPresent?(["target": self.reactTag as Any])
|
||||||
} else {NSLog("not fullscreen")}
|
}
|
||||||
|
} else {
|
||||||
|
NSLog("not fullscreen")
|
||||||
|
if (_fullscreenUncontrolPlayerPresented) {
|
||||||
|
_fullscreenUncontrolPlayerPresented = false;
|
||||||
|
|
||||||
|
self.onVideoFullscreenPlayerWillDismiss?(["target": self.reactTag as Any])
|
||||||
|
self.onVideoFullscreenPlayerDidDismiss?(["target": self.reactTag as Any])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.reactViewController().view.frame = UIScreen.main.bounds
|
||||||
|
self.reactViewController().view.setNeedsLayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import AVKit
|
|||||||
|
|
||||||
class RCTVideoPlayerViewController: AVPlayerViewController {
|
class RCTVideoPlayerViewController: AVPlayerViewController {
|
||||||
|
|
||||||
var rctDelegate:RCTVideoPlayerViewControllerDelegate!
|
weak var rctDelegate: RCTVideoPlayerViewControllerDelegate?
|
||||||
|
|
||||||
// Optional paramters
|
// Optional paramters
|
||||||
var preferredOrientation:String?
|
var preferredOrientation:String?
|
||||||
@ -19,11 +19,9 @@ class RCTVideoPlayerViewController: AVPlayerViewController {
|
|||||||
|
|
||||||
override func viewDidDisappear(_ animated: Bool) {
|
override func viewDidDisappear(_ animated: Bool) {
|
||||||
super.viewDidDisappear(animated)
|
super.viewDidDisappear(animated)
|
||||||
|
|
||||||
if rctDelegate != nil {
|
rctDelegate?.videoPlayerViewControllerWillDismiss(playerViewController: self)
|
||||||
rctDelegate.videoPlayerViewControllerWillDismiss(playerViewController: self)
|
rctDelegate?.videoPlayerViewControllerDidDismiss(playerViewController: self)
|
||||||
rctDelegate.videoPlayerViewControllerDidDismiss(playerViewController: self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
|
Loading…
Reference in New Issue
Block a user