如何告诉活动视图控制器何时调用applicationDidBecomeActive?

How to tell the active view controller when applicationDidBecomeActive is called?

提问人:David John 提问时间:4/28/2012 最后编辑:Rashwan LDavid John 更新时间:2/11/2021 访问量:22887

问:

我觉得我在这里错过了一个技巧......

我只想在调用 applicationDidBecomeActive 时在当前活动视图控制器上调用 viewDidLoad 或 viewDidAppear,这样当应用程序从后台再次启动时,我就可以重置一些动画或其他内容。我的一些观点并不在乎,但其他观点确实需要知道。

我正在使用 Storyboard,我的应用程序委托文件具有标准函数 - 但所有函数都带有 EMPTY 正文。例如,didFinishLaunchingWithOptions 仅返回 YES,不执行任何其他操作。故事板会自动完成我猜到的一切。

那么,我如何从我相当空白、无信息的应用程序委托中与当前视图控制器交谈呢?

iOS iPhone Swift Xcode-Storyboard

评论

0赞 geraldWilliam 4/28/2012
可能有一种更简单的方法可以做到这一点,但我认为如果你在应用程序委托@property(强、非原子)UIViewController *currentViewController *currentViewController 中添加一个属性,它会起作用。然后,每次加载视图时,回调委托以设置该属性。然后在 applicationWillResignActive 中,将其保存到 NSUserDefaults 并在应用程序再次激活时检查值?

答:

0赞 Joseph DeCarlo 4/28/2012 #1

与其尝试跟踪哪个 ViewController 是最新的,不如从 AppDelegate 发送 NSNotification 并在 ViewController 中订阅它。这样,视图控制器就会跟踪它是否需要调用 viewDidAppear。

评论

0赞 David John 4/28/2012
是的,这就是我所采用的。这完全有意义,因为我的大多数控制器都不需要注册。
23赞 Brandon Brodjeski 4/28/2012 #2

我建议使用通知。

在应用委托的 applicationdidBecomeActive 方法中,放入以下代码:

[[NSNotificationCenter defaultCenter] postNotificationName:@"appDidBecomeActive" object:nil];

在当前活动视图控制器的 init 方法中,订阅通知。

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(updateStuff)        
                                             name:@"appDidBecomeActive" 
                                           object:nil];

在控制器中实现“updateStuff”方法,当应用程序处于活动状态时,您应该能够执行任何操作。

评论

0赞 David John 4/28/2012
谢谢,效果很好,似乎是建议的最整洁的方法。虽然我有点担心正确删除观察者。我正在以模式方式使用一堆ViewController,因此它们被加载和卸载了很多。我在 -(void)viewDidLoad 中调用 addObserver,在 -(void)viewDidUnload 中调用 removeObserver。似乎工作正常。我会进一步测试......
0赞 Maksim 4/28/2012
别忘了做 [[NSNotificationCenter defaultCenter] removeObserver:self name:@“appDidBecomeActive” object:nil];in viewDid卸载
2赞 Joseph DeCarlo 4/28/2012
不应忘记在 dealloc 中 removeObserver,因为 viewDidUnload 不会在所有场景中都被调用
1赞 David John 4/29/2012
我已经测试了两次删除它,冗余删除它很好。出于这个原因,我把它放在 viewDidUnload 和 dealloc 中,我想我已经涵盖了我的所有基础。谢谢大家...
4赞 MattyG 3/15/2014
请参阅 einsteinx2 的答案,以获得更优雅的解决方案,使用现有的 UIApplicationDidBecomeActiveNotification 通知。
0赞 Jesse Gumpo 4/28/2012 #3

您的 AppDelegate 将具有一个 window 属性,该窗口将具有一个 rootViewController 属性。您可以在此处找到您的 viewController。

如果您使用的是 TabBarController,则 rootviewcontroller 将是 tabbarcontroller,您可以调用 tabbarcontroller 的 selectedViewController 来获取当前 viewController。

UIViewController *rootViewController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
if ([rootViewController isKindOfClass:[UITabBarController Class]])
    rootViewController = ((UITabBarController *)rootViewController).selectedViewController;
else if ([rootViewController isKindOfClass:[UINavigationController Class]])
    rootViewController = ((UINavigationController *)rootViewController).topViewController;

[rootViewController viewDidAppear];

如果具有包含导航控制器或模式视图的更复杂的视图层次结构,则可以调用 presentedViewController 或 topViewController。

评论

0赞 Hamid 9/17/2012
这个窗口属性对我不起作用,它给了我这个错误:使用未声明的标识符“window”。你能更新答案吗,因为我真的需要知道屏幕上是哪个视图,然后更新它。
0赞 Hamid 9/30/2012
感谢您的更新,我更改了它,它抛出了一个异常,如下所示: :(对于这行代码:unrecognized selector sent to instanceUIViewController *vc = tabbarController.selectedViewController;
55赞 Ben Baron 6/12/2012 #4

OS 会自动发送通知,而不是从应用委托发送通知,你可以观察:

[[NSNotificationCenter defaultCenter] addObserver:self
                                      selector:@selector(initSongInfo)
                                      name:UIApplicationDidBecomeActiveNotification
                                      object:nil];

当然,请确保在 Dealloc 方法之前或内部的某个时间停止观察,方法是调用:

[[NSNotificationCenter defaultCenter] removeObserver:self 
                                      name:UIApplicationDidBecomeActiveNotification 
                                      object:nil];

评论

3赞 MattyG 3/15/2014
这是比布兰登·布罗杰斯基(Brandon Brodjeski)目前接受的答案更好的解决方案。
2赞 Collin Thomas 2/13/2015
这是正确的方法
1赞 Buddhisthead 8/19/2021
在构建框架且无法向应用程序委托添加代码时,这是一种更好的方法。
13赞 Rashwan L 7/8/2016 #5

Swift 版本:

您可以在 viewDidLoad 中添加此行

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(viewDidBecomeActive), name: UIApplicationDidBecomeActiveNotification, object: nil)

func viewDidBecomeActive(){
    print("viewDidBecomeActive")
}

Swift 5.x 版本

NotificationCenter.default.addObserver(self, selector: #selector(viewDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)

@objc func viewDidBecomeActive() {
    print("viewDidBecomeActive")
}

评论

0赞 xhinoda 5/10/2019
swift 4 和 5 NotificationCenter.default.addObserver(self, selector: #selector(viewDidBecomeActive), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
2赞 Oz Shabat 4/30/2019 #6

好吧,这是相当灾难性的。

你们必须注意事件注册/取消注册,因为可能会导致内存泄漏。

要使一切正常,您需要设置一个标志,该标志知道注册状态是什么:您是否登录了后台事件。请注意,当用户看到视图控制器(如果他来自不同的视图控制器)或他从主屏幕访问视图控制器时,您需要注册到事件。

当您将视图控制器留给其他控制器时,您还需要取消注册。

总之:

斯威夫特 4:

private var registeredToBackgroundEvents = false

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    registerToBackFromBackground()
}

/// register to back from backround event
private func registerToBackFromBackground() {
    if(!registeredToBackgroundEvents) {
        NotificationCenter.default.addObserver(self, 
        selector: #selector(viewDidBecomeActive), 
        name: UIApplication.didBecomeActiveNotification, object: nil)
        registeredToBackgroundEvents = true
    }
}

/// unregister from back from backround event
private func unregisterFromBackFromBackground() {
    if(registeredToBackgroundEvents) {
        NotificationCenter.default.removeObserver(self, 
        name: UIApplication.didBecomeActiveNotification, object: nil)
        registeredToBackgroundEvents = false
    }

}

@objc func viewDidBecomeActive(){
    logicManager.onBackFromStandby()
}


override func viewWillDisappear(_ animated: Bool) {
    unregisterFromBackFromBackground()
}