提问人:David John 提问时间:4/28/2012 最后编辑:Rashwan LDavid John 更新时间:2/11/2021 访问量:22887
如何告诉活动视图控制器何时调用applicationDidBecomeActive?
How to tell the active view controller when applicationDidBecomeActive is called?
问:
我觉得我在这里错过了一个技巧......
我只想在调用 applicationDidBecomeActive 时在当前活动视图控制器上调用 viewDidLoad 或 viewDidAppear,这样当应用程序从后台再次启动时,我就可以重置一些动画或其他内容。我的一些观点并不在乎,但其他观点确实需要知道。
我正在使用 Storyboard,我的应用程序委托文件具有标准函数 - 但所有函数都带有 EMPTY 正文。例如,didFinishLaunchingWithOptions 仅返回 YES,不执行任何其他操作。故事板会自动完成我猜到的一切。
那么,我如何从我相当空白、无信息的应用程序委托中与当前视图控制器交谈呢?
答:
与其尝试跟踪哪个 ViewController 是最新的,不如从 AppDelegate 发送 NSNotification 并在 ViewController 中订阅它。这样,视图控制器就会跟踪它是否需要调用 viewDidAppear。
评论
我建议使用通知。
在应用委托的 applicationdidBecomeActive 方法中,放入以下代码:
[[NSNotificationCenter defaultCenter] postNotificationName:@"appDidBecomeActive" object:nil];
在当前活动视图控制器的 init 方法中,订阅通知。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateStuff)
name:@"appDidBecomeActive"
object:nil];
在控制器中实现“updateStuff”方法,当应用程序处于活动状态时,您应该能够执行任何操作。
评论
您的 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。
评论
unrecognized selector sent to instance
UIViewController *vc = tabbarController.selectedViewController;
OS 会自动发送通知,而不是从应用委托发送通知,你可以观察:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(initSongInfo)
name:UIApplicationDidBecomeActiveNotification
object:nil];
当然,请确保在 Dealloc 方法之前或内部的某个时间停止观察,方法是调用:
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:nil];
评论
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")
}
评论
好吧,这是相当灾难性的。
你们必须注意事件注册/取消注册,因为可能会导致内存泄漏。
要使一切正常,您需要设置一个标志,该标志知道注册状态是什么:您是否登录了后台事件。请注意,当用户看到视图控制器(如果他来自不同的视图控制器)或他从主屏幕访问视图控制器时,您需要注册到事件。
当您将视图控制器留给其他控制器时,您还需要取消注册。
总之:
斯威夫特 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()
}
评论