检测应用程序何时进入我的视图背景的最佳方法是啥?
Posted
技术标签:
【中文标题】检测应用程序何时进入我的视图背景的最佳方法是啥?【英文标题】:What's the best way to detect when the app is entering the background for my view?检测应用程序何时进入我的视图背景的最佳方法是什么? 【发布时间】:2012-02-19 04:15:35 【问题描述】:我有一个视图控制器,它使用NSTimer
来执行一些代码。
检测应用何时进入后台以便我可以暂停计时器的最佳方法是什么?
【问题讨论】:
【参考方案1】:在 Swift 5.1 中
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(applicationWillResignActive), name: UIApplication.willResignActiveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
override func viewWillDisappear(_ animated: Bool)
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
@objc private func applicationWillResignActive()
@objc private func applicationDidBecomeActive()
【讨论】:
【参考方案2】:这是使用闭包的更好解决方案
声明观察者
var backgroundObserver: NSObjectProtocol?
在 viewDidLoad 中初始化观察者
backgroundObserver = NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: .main) [weak self] notification in
// Do what you want to do when app would go to background/ resign active
不要忘记删除 deinit 中的观察者
deinit
if let observer = backgroundObserver
NotificationCenter.default.removeObserver(observer)
【讨论】:
【参考方案3】:在 Swift 4.1 中:
我使用闭包版本:
var observer: NSObjectProtocol!
// inside init or viewDidLoad:
observer = NotificationCenter.default.addObserver(forName: .UIApplicationWillResignActive, object: nil, queue: nil) _ in
print("willResignActive")
deinit
NotificationCenter.default.removeObserver(observer)
addObserver
方法返回一个不透明的对象,需要在某个时候移除。
【讨论】:
【参考方案4】:斯威夫特 4:
init()
NotificationCenter.default.addObserver(self,
selector: #selector(applicationWillResignActive),
name: NSNotification.Name.UIApplicationWillResignActive,
object: nil)
deinit
NotificationCenter.default.removeObserver(self,
name: NSNotification.Name.UIApplicationWillResignActive,
object: nil)
@objc private func applicationWillResignActive()
self.header.blur.effect = nil
【讨论】:
【参考方案5】:只是一个旁注: 如果您注册控制器 A 以通知后台运行,请注意即使您(例如..)推送第二个控制器 B 并且您正在显示 B,它也会被调用: 如果此行为不正确,最好在
中注册/注销didAppear/WillDisappear。
【讨论】:
【参考方案6】:在 Swift 4.0 中
override func viewDidLoad()
super.viewDidLoad()
let app = UIApplication.shared
//Register for the applicationWillResignActive anywhere in your app.
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.applicationWillResignActive(notification:)), name: NSNotification.Name.UIApplicationWillResignActive, object: app)
@objc func applicationWillResignActive(notification: NSNotification)
【讨论】:
您在哪里取消注册通知? @thexande 如果我是正确的,Swift 4 会为你做这件事,你不必再取消注册通知了(除非你等不及了 ;-) @StephanePaquet 来自 Apple 的文档:“如果您的应用针对 ios 9.0 及更高版本或 macOS 10.11 及更高版本,则无需在其 dealloc 方法中取消注册观察者。” :)【参考方案7】:对于那些希望在 Swift 中执行此操作的人:
在init
:
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(applicationWillResignActive), name: UIApplicationWillResignActiveNotification, object: nil)
在deinit
:
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationWillResignActiveNotification, object: nil)
响应通知:
dynamic private func applicationWillResignActive()
// Do things here
Apple 鼓励我们在 Swift 中尽可能避免使用动态调度和 Objective-C 选择器,但这仍然是最方便的方法。
【讨论】:
【参考方案8】:您可以让任何感兴趣的课程在应用程序进入后台时接收通知。这是将这些类与 AppDelegate 耦合的一个很好的替代方法。
初始化上述类时:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
响应通知
-(void)appWillResignActive:(NSNotification*)note
-(void)appWillTerminate:(NSNotification*)note
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil];
【讨论】:
我必须对这段代码进行一个小修复:通过在@selector
中的方法名称中添加一个冒号,即将@selector(appWillResignActive)
替换为@selector(appWillResignActive:)
(对于@987654326 也一样) @)。
@Piovezan,您需要“:”的原因是因为无论您调用您的方法,它仍然必须采用“..一个且只有一个参数(NSNotification 的一个实例)”。 - 只需 Alt + 左键单击 addObserver 声明即可了解更多信息。
很好的答案!谢谢你救了我一些头发!!
willResignActive 并不意味着它会进入后台——它意味着它会处于非活动状态。例如,您的应用程序顶部的来电将使您处于非活动状态,系统级对话框弹出窗口也会使您处于非活动状态。 UIApplicationDidEnterBackground 是实际进入后台的通知。【参考方案9】:
- (void)applicationWillResignActive:(UIApplication *)application
在您的应用委托上。您也可以在其他对象上注册UIApplicationWillResignActiveNotification
通知。
不过,您不一定需要暂停计时器。如果你什么都不做,应用程序无论如何都会进入睡眠状态并且不会执行任何代码。据推测,当您再次活跃时(如果您这样做),您的计时器将触发。如果您需要做一些特别的事情,您也可以注册“已激活”委托方法和通知。
【讨论】:
如前所述,如果您只针对 4.0 及更高版本,则有一个“后台”版本与 resign active 非常相似。 “活动”版本回到 2.0。 +1,当我提出我的答案时,没有意识到你有通知部分 严格来说,退出活动状态的应用可能不会以后台状态结束(例如,在电话或短信等临时中断的情况下)。 @marco:同意。我有点快和松。很多人(不能确定 OP)并没有真正区分非活动和背景。我想,考虑到问题的措辞方式,不活跃是他正在寻找的更多,但也许我去那里很远。 FWIW,来自操作系统的某些模式弹出窗口(例如,用于网络和位置要求)也将触发辞职活动。【参考方案10】:在您的应用程序 AppDelegate 上,(void)applicationDidEnterBackground:(UIApplication *)application
方法将被 iOS 调用。你可以在那里停止你的计时器。
【讨论】:
您的应用也可以为自己注册 UIApplicationDidEnterBackgroundNotification 通知。以上是关于检测应用程序何时进入我的视图背景的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章