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


77

我有一个视图控制器,它使用NSTimer来执行一些代码。

检测应用何时进入后台以便暂停计时器的最佳方法是什么?

Answers:


171

当应用程序进入后台时,您可以对任何感兴趣的类进行接收通知。这是将这些类与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];

}

2
我必须对此代码进行小幅修复:通过在内的方法名称中添加冒号@selector,即替换@selector(appWillResignActive)@selector(appWillResignActive:)(与相同@selector(appWillTerminate:))。
Piovezan

@Piovezan,之所以需要“:”是因为无论您调用什么方法,它都必须仍然使用“ ..一个且只有一个参数(NSNotification的一个实例)”。-只需Alt +左​​键单击addObserver声明即可了解更多信息。
serge-k 2015年

好答案!谢谢您为我省了一些力气!!
Septronic

willResignActive并不意味着它会进入后台,而是意味着它将变为非活动状态。例如,在应用程序顶部的传入呼叫将使您处于非活动状态,而系统级对话框弹出窗口也会使您处于非活动状态。UIApplicationDidEnterBackground是实际进入后台的通知。
chadbag

25

在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) {

}

1
您在哪里在哪里取消注册通知?
thexande

@thexande,如果我说得对,Swift 4会帮您完成,您就不必注销通知了(除非您不能等待;-)
Stephane Paquet,

1
苹果文档中的@StephanePaquet:“如果您的应用程序针对iOS 9.0及更高版本或macOS 10.11及更高版本,则无需在其dealloc方法中注销观察者。” :)
罗布VS

10

在您的应用程序AppDelegate上(void)applicationDidEnterBackground:(UIApplication *)application,iOS将调用该方法。您可以在那里停止计时器。


2
您的应用还可以自行注册UIApplicationDidEnterBackgroundNotification通知。
马可(Marco)

8

对于那些希望在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选择器,但这仍然是最方便的方法。


2

在快速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方法返回一个不透明的对象,需要在某个时候将其删除。


1

仅附带说明:如果您注册了一个要在后台通知的控制器A,请注意即使您(例如..)按下另一个控制器B并且您正在显示B,它也会被调用:如果此行为不正确,最好在中注册/注销

didAppear / WillDisappear。


0

- (void)applicationWillResignActive:(UIApplication *)application在您的应用程序委托上。您还可以注册UIApplicationWillResignActiveNotification其他对象的通知。

不过,您不一定需要暂停计时器。如果您不执行任何操作,则该应用程序仍将进入睡眠状态,并且不会执行任何代码。大概您的计时器会在您再次活跃时触发(如果您这样做)。如果您需要做一些特别的事情,则可以注册“活跃”委托方法和通知。


如前所述,有一个“后台”版本与主动退出非常相似,如果您的目标只是4.0及更高版本。“活动”版本可追溯至2.0。
smparkes 2012年

+1,当我提出答案时没有意识到您有通知部分
Jesse Black

1
严格来说,应用程序退出活动状态可能不会以后台状态结束(例如,在诸如电话或SMS的临时中断的情况下)。
Marco

1
@marco:同意。我当时快而松散。许多人(不确定OP)并没有真正区分不活动和背景。我认为,考虑到问题的表达方式,不活跃是他一直在寻找的东西,但也许我去了那么远。FWIW,来自操作系统的某些模式弹出窗口(例如,用于网络和位置要求)也会触发主动辞职。
smparkes 2012年

0

斯威夫特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
}

0

这是使用闭包的更好的解决方案

宣布观察员

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)
    } 
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.