这可能很容易,但我真的找不到或理解如何得到通知,当一个视图去后台,并返回使用SceneDelegate
。如果我有一个viewController
通过回到主菜单或类似的东西进入背景,我如何通过sceneWillResignActive
检测它?
我发现在这里可以这样做:
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.willResignActiveNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(appBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
更具体地说,我有这个ViewController.swift:
import Foundation
import UIKit
import AVKit
class IntroViewController : UIViewController {
@IBOutlet weak var videoView: UIView!
@IBOutlet weak var introLabel: UILabel!
var player: AVPlayer?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
playVideo()
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self)
if let player = player {
player.pause()
}
player = nil
}
private func playVideo() {
if player != nil {
player!.play()
} else {
guard let path = Bundle.main.path(forResource: "intro_video", ofType:"mp4") else {
debugPrint("intro.MP4 not found")
return
}
player = AVPlayer(url: URL(fileURLWithPath: path))
player!.actionAtItemEnd = .none
let playerFrame = CGRect(x: 0, y: 0, width: videoView.frame.width, height: videoView.frame.height)
NotificationCenter.default.addObserver(self,
selector: #selector(playerItemDidReachEnd(notification:)),
name: .AVPlayerItemDidPlayToEndTime,
object: player!.currentItem)
let playerController = AVPlayerViewController()
playerController.player = player
playerController.videoGravity = .resizeAspectFill
playerController.view.frame = playerFrame
playerController.showsPlaybackControls = false
addChild(playerController)
videoView.addSubview(playerController.view)
playerController.didMove(toParent: self)
player!.play()
player!.rate = 1.3
}
}
@objc func playerItemDidReachEnd(notification: Notification) {
let mainViewController = self.storyboard!.instantiateViewController(withIdentifier: "main_view_controller") as! MainViewController
player!.pause()
present(mainViewController, animated:true, completion:nil)
}
@IBAction func skipVideo(_ sender: Any) {
if player != nil {
player?.pause()
player = nil
}
let mainViewController = self.storyboard!.instantiateViewController(withIdentifier: "main_view_controller") as! MainViewController
present(mainViewController, animated:true, completion:nil)
}
}
还有SceneDelegate.swift
:
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
当用户离开应用程序时,我希望能够暂停并重新启动播放器。对于启动播放器,应该以某种方式从sceneDidBecomeActive
调用,因为我理解它。我不明白的是如何在sceneDidBecomeActive
中,应该呈现的视图控制器是我想要的。
sceneDidBecomeActive
(当然)每次我回到应用程序时被调用,无论我从哪个ViewController
离开它。
在引用旧方法的链接中,似乎有一些通知过程,您可以为其分配lambda。如果我在SceneDelegate
中引用了ViewController
,我必须以某种方式检查,看看它是否应该成为活动的?
我不觉得遵循我发现的关于SceneDelegates
的教程是非常微不足道的。他们主要谈论Appdelegate和你能做的事情之间的区别,但从来没有真正如何去做。
你有相同的resignActive, enterBackground在场景委托和在应用程序委托。你能做的是在sceneDelegate中有一个对视图控制器的引用,并在这些场景委托方法之一运行时调用视图控制器的一些方法(你可以定义一个视图控制器将实现的协议)。