当视图控制器进入后台时收到通知
Posted
技术标签:
【中文标题】当视图控制器进入后台时收到通知【英文标题】:Getting notification when viewcontroller goes to background 【发布时间】:2021-10-21 05:25:21 【问题描述】:这可能很容易,但我真的不知道如何在视图进入后台并使用SceneDelegate
返回时获得通知。如果我有一个 viewController
通过返回主菜单或类似的东西进入后台,我如何通过 sceneWillResignActive
检测到它?
我发现 here 可以这样做:
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 之间的差异以及您可以做什么,但从不谈论如何实际去做。
【问题讨论】:
您能否定义一下“进入后台”对您意味着什么?当用户点击 iPhone 上的主页按钮或打开其他应用程序并返回时,应用程序作为一个整体进入后台并恢复,这也是AppDelegate
和 SceneDelegate
通知的内容。但是您所指定的问题似乎更像viewWillDisappear
和viewWillAppear
,您可以查看ViewController
生命周期以获取更多详细信息***.com/questions/5562938/…
【参考方案1】:
场景委托中的 resignActive、enterBackground 与应用委托中的相同。您可以做的是在 sceneDelegate 中引用您的视图控制器,并在其中一个场景委托方法运行时调用视图控制器的某些方法(您可以定义视图控制器将实现的协议)。
【讨论】:
我如何知道哪个视图控制器将是活动的?sceneDidBecomeActive
总是在我回去的时候被调用。我有不止一个ViewController
,如果我要回到那个,我只会调用特定的方法。
你可以在post找到你想要的东西以上是关于当视图控制器进入后台时收到通知的主要内容,如果未能解决你的问题,请参考以下文章