无法通过谷歌在iOS应用程序中正确投射video

我正在开发一个基于AVPlayer的自定义video播放器项目。 试图整合谷歌投。 我已经做了基于谷歌的集成: https ://codelabs.developers.google.com/codelabs/cast-videos-ios/但转换为swift。 一切似乎工作正常,当投,如果video播放器打开,并且有连接的设备(或者如果我从面板连接),我形成文件的元信息,它传递给谷歌投下 – 一切工作正常。

但是,我有奇怪的行为:1)开始投射,打开video,然后是另一个video,然后是第三个video。 2)停止投射3)转到另一个video,启用投射,但不启动此video。 它开始铸造我先前打开的第一个video….

我试图find清除caching或队列的任何方法,但没有..请帮助

class VideoVC: UIViewController, UIGestureRecognizerDelegate, GCKSessionManagerListener { var filmTitle: String! var toPass: String! var film: MovieDetails! var filmDetails: Movie! var sessionManager: GCKSessionManager? var castSession: GCKCastSession? var castMediaController: GCKUIMediaController? var checkPlayed = 0 override func viewDidLoad() { super.viewDidLoad() sessionManager = GCKCastContext.sharedInstance().sessionManager sessionManager?.add(self) castMediaController = GCKUIMediaController() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if let videoURL = toPass { if let video = URL(string: videoURL) { player = AVPlayer(url: video) player.allowsExternalPlayback = true player.usesExternalPlaybackWhileExternalScreenIsActive = true playerController.player = player self.addChildViewController(playerController) self.view.addSubview(playerController.view) playerController.view.frame = self.view.frame self.view.sendSubview(toBack: playerController.view) } } if isCastEnabled() { playSelectedItemRemotely() } } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) player.replaceCurrentItem(with: nil) } func buildMediaInformation() -> GCKMediaInformation { let metaData = GCKMediaMetadata(metadataType: GCKMediaMetadataType(rawValue: 1)!) metaData.setString(filmTitle, forKey: kGCKMetadataKeyTitle) if let imageUrl = URL(string: filmDetails.poster_cast!) { let image = GCKImage(url: imageUrl, width: 340, height: 450) metaData.addImage(image) } if let episode = film.serial_episode, let season = film.serial_season, season != "", episode != "", let title = film.title, title != "" { let subtitle = "\(title) \(episode) серия \(season) сезон" metaData.setString(subtitle, forKey: kGCKMetadataKeySubtitle) } let duration = Double(film.duration!) let mediaInfo = GCKMediaInformation(contentID: toPass!, streamType: GCKMediaStreamType.buffered, contentType: film.contentType!, metadata: metaData as GCKMediaMetadata, streamDuration: duration, mediaTracks: nil, textTrackStyle: nil, customData: nil) print("toPass: \(toPass!)") print("duration: \(duration)") return mediaInfo } func playSelectedItemRemotely() { let castSession = GCKCastContext.sharedInstance().sessionManager.currentCastSession if (castSession != nil) { castSession?.remoteMediaClient?.loadMedia(self.buildMediaInformation(), autoplay: true) self.dismiss(animated: true, completion: nil) } else { print("no castSession!") } } func sessionManager(_ sessionManager: GCKSessionManager, didStart session: GCKSession) { playSelectedItemRemotely() } func sessionManager(_ sessionManager: GCKSessionManager, didResumeSession session: GCKSession) { } func sessionManager(_ sessionManager: GCKSessionManager, didEnd session: GCKSession, withError error: Error?) { let castSession = GCKCastContext.sharedInstance().sessionManager.currentCastSession castSession?.endAndStopCasting(true) } func sessionManager(_ sessionManager: GCKSessionManager, didFailToStart session: GCKSession, withError error: Error) { Utils.showOverAnyVC("Ошибка подключения", message: "Попробуйте еще раз!") } func isCastEnabled() -> Bool { switch GCKCastContext.sharedInstance().castState { case GCKCastState.connected: print("cast connected") return true case GCKCastState.connecting: print("cast connecting") return true case GCKCastState.notConnected: print("cast notConnected") return false case GCKCastState.noDevicesAvailable: print("cast noDevicesAvailable") return false } }} 

和我的appdelegate:

类AppDelegate:UIResponder,UIApplicationDelegate,GCKLoggerDelegate,UNUserNotificationCenterDelegate {

 var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. let options = GCKCastOptions(receiverApplicationID: "F443E49F") GCKCastContext.setSharedInstanceWith(options) GCKLogger.sharedInstance().delegate = self let appStoryboard = UIStoryboard(name: "NewMain", bundle: nil) let navigationController = appStoryboard.instantiateViewController(withIdentifier: "MainNavigation") let castContainerVC: GCKUICastContainerViewController = GCKCastContext.sharedInstance().createCastContainerController(for: navigationController) castContainerVC.miniMediaControlsItemEnabled = true self.window = UIWindow(frame: UIScreen.main.bounds) self.window?.rootViewController = castContainerVC self.window?.makeKeyAndVisible() GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true return true } func logMessage(_ message: String, fromFunction function: String) { print("message: \(function)") }} 

在可能的解决scheme可能是由于:

 sessionManager?.add(self) 

你添加委托,但你没有清除它。 因此,由于会话pipe理器的保留引用, VideoVC永远不会被销毁。 当您重新打开VideoVC ,会话pipe理器仍然在第一次加载时访问VideoVC

正因为如此,以下称为:

 func sessionManager(_ sessionManager: GCKSessionManager, didStart session: GCKSession) { 

这是在您的第一个VideoVC ,它现在有错误的文件信息被调用。

您可以通过将print(self)放入上面的方法来监视它,并查看内存指针值。 检查它是否与viewDidLoad调用的内存指针值相同

更新

为了更好地pipe理委托,请更改以下方法: viewDidDisappear()

 override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) player.replaceCurrentItem(with: nil) //this stops the session manager sending callbacks to your VideoVC sessionManager.remove(self) }