检测应用程序何时进入我的视图背景的最佳方法是啥?

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 通知。

以上是关于检测应用程序何时进入我的视图背景的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

比较两个 NSArray 并检测更改的最佳方法是啥

连接/断开数据库的最佳实践是啥?

连接/断开数据库的最佳实践是啥?

如何检测自定义表格视图单元格何时离开屏幕?

在应用扩展中检测方向的最佳方法是啥?

如何检测表视图中的项目何时更改?