Функция класса ObservedObject не вызывается при срабатывании протокола - PullRequest
0 голосов
/ 27 мая 2020

При реализации протоколов SDK Google Interactive Media Ads (IMA) мой mediaPlayer / audioManager, который является объектом AVPlayer, не приостанавливается во время метода делегата adsManagerDidRequestContentPause. Мой mediaPlayer соответствует ObservableObject, поэтому я думаю, что проблема возникла, но я не на 100% уверен.

Когда я нажимаю кнопку воспроизведения, я проигрываю звук и запрашиваю рекламу из моего класса adsManager. Проблема в том, что видео перед прокруткой воспроизводится, но звук проигрывателя содержимого воспроизводится поверх предварительной прокрутки. Звук от проигрывателя контента должен приостанавливаться во время воспроизведения предварительной прокрутки и возобновляться после его завершения. Как вы увидите в коде, AudioManager также является одноэлементным классом.

Вот код, когда пользователь нажимает кнопку воспроизведения.

@ObservedObject var manager = AudioManager.sharedInstance

func didTapPlayButton(){
    isPlaying.toggle()
    if isPlaying {
        audioManager.playLiveStream(with: pageInfo.tritonMount)
        adManager.requestAds()
    } else {
        audioManager.pause()
    }
}

А вот класс adManager с Google IMA делегировать методы. После установки точек останова в каждом методе делегата я обнаружил, что каждый вызов audioManager вызывается успешно, однако звук из audioManager фактически не приостанавливается.

@ObservedObject var manager = AudioManager.sharedInstance

func setUpContentPlayer() {
    contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: player)
    // Create a player layer for the player.
    playerLayer = AVPlayerLayer(player: player)
    playerLayer!.frame = videoView.underlyingView.layer.bounds
    videoView.underlyingView.layer.addSublayer(playerLayer!)
}

func setUpAdsLoader() {
    adsLoader = IMAAdsLoader(settings: nil)
    adsLoader!.delegate = self
}

func requestAds() {
    // Create an ad display container for ad rendering.
    let adDisplayContainer = IMAAdDisplayContainer(adContainer: videoView.underlyingView, companionSlots: nil)

    // Create an ad request with our ad tag, display container, and optional user context.
    let request = IMAAdsRequest(
        adTagUrl: kLivePrerollVastTag,
        adDisplayContainer: adDisplayContainer,
        contentPlayhead: contentPlayhead,
        userContext: nil)

    adsLoader!.requestAds(with: request)
}

func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) {
    // Grab the instance of the IMAAdsManager and set ourselves as the delegate
    adsManager = adsLoadedData.adsManager
    adsManager!.delegate = self

    // Create ads rendering settings and tell the SDK to use the in-app browser.
    let adsRenderingSettings = IMAAdsRenderingSettings()

    adsRenderingSettings.webOpenerPresentingController = viewController

    // Initialize the ads manager.
    adsManager!.initialize(with: adsRenderingSettings)
}

//Ads Manager recieved ad request and is loading and starting ad
func adsManager(_ adsManager: IMAAdsManager!, didReceive event: IMAAdEvent!) {
    if (event.type == IMAAdEventType.LOADED) {
        // When the SDK notifies us that ads have been loaded, play them.
        adsManager.start()
    }
}

//Ads manager failed to receive ad request
func adsLoader(_ loader: IMAAdsLoader!, failedWith adErrorData: IMAAdLoadingErrorData!) {
    print("Error loading ads: \(String(describing: adErrorData.adError.message))")
    audioManager.resume()
}

func adsManager(_ adsManager: IMAAdsManager!, didReceive error: IMAAdError!) {
    // Something went wrong with the ads manager after ads were loaded. Log the
    // error and play the content.
    NSLog("AdsManager error: \(String(describing: error.message))")
    audioManager.resume()
}

/*Ads manager received request, initiated avplayer and is now
requesting player be paused in order or the Ads manager to play preroll*/
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager!) {
    // The SDK is going to play ads, so pause the content.
    audioManager.pause()
}
/*Ads manager received request, played the preroll and is now
 requesting avplayer to resume live stream*/
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager!) {
    // The SDK is done playing ads (at least for now), so resume the content.
    audioManager.resume()
}

AudioManagerClass:

    /// Upon setting this property any observers for 'currentItem' as well as any time observers will
/// be removed from the old value where applicable and added to the new value where applicable.
var player: AVPlayer? {
    didSet {
        oldValue?.removeObserver(self, forKeyPath: "currentItem", context: &AudioManager.ObserveAVPlayerCurrentItem)
        oldValue?.removeObserver(self, forKeyPath: "rate", context: &AudioManager.ObserveAVPlayerRate)
        guard let player = self.player else { return }

        player.addObserver(self, forKeyPath: "currentItem", options: [.initial, .new], context: &AudioManager.ObserveAVPlayerCurrentItem)
        player.addObserver(self, forKeyPath: "rate", options: [.initial, .new], context: &AudioManager.ObserveAVPlayerRate)
        player.automaticallyWaitsToMinimizeStalling = false
        if let tmpObs = timeObserver {
            print("Already have timeobserver, removing it")
            oldValue?.removeTimeObserver(tmpObs)
            timeObserver = nil
        }

        timeObserver = player.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1,preferredTimescale: 1),
            queue: nil,
            using: timeObserverCallback) as AnyObject?
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...