从后台打开应用程序时不调用 ViewDidAppear

我有一个视图控制器,其中我的值为0(标签) ,当我从另一个 ViewController打开该视图控制器时,我已经将 viewDidAppear设置为在标签上设置值20。它工作的很好,但当我关闭我的应用程序,然后再次我打开我的应用程序,但是值没有改变,因为 viewDidLoadviewDidAppearviewWillAppear没有被调用。我打开应用程序的时候怎么打电话。我需要从 applicationDidBecomeActive做什么吗?

114587 次浏览

只要让您的视图控制器注册 UIApplicationWillEnterForegroundNotification通知并做出相应的反应。

使用 Objective-C

你应该在你的 ViewControllerviewDidLoad方法中注册一个 UIApplicationWillEnterForegroundNotification,当应用程序从后台回来时,你可以在为通知注册的方法中做任何你想做的事情。当应用程序从后台返回到前台时,不会调用 ViewController出现出现

-(void)viewDidLoad{


[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doYourStuff)


name:UIApplicationWillEnterForegroundNotification object:nil];
}


-(void)doYourStuff{


// do whatever you want to do when app comes back from background.
}

不要忘记注销注册的通知。

-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

注意 如果你为 UIApplicationDidBecomeActiveNotification注册了 viewController,那么每当你的应用变得活跃时,你的方法就会被调用,不建议为这个通知注册 viewController

用斯威夫特

要添加观察者,可以使用以下代码

 override func viewDidLoad() {
super.viewDidLoad()


NotificationCenter.default.addObserver(self, selector: "doYourStuff", name: UIApplication.willEnterForegroundNotification, object: nil)
}


func doYourStuff(){
// your code
}

要删除观察者,你可以使用迅捷的 deinit 函数。

deinit {
NotificationCenter.default.removeObserver(self)
}

出于对事件的确切顺序的好奇,我安装了一个应用程序,如下所示: (@Zohaib,你可以使用下面的 NSNotificationCenter 代码来回答你的问题)。

// AppDelegate.m


- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(@"app will enter foreground");
}


- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(@"app did become active");
}


// ViewController.m


- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"view did load");


[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}


- (void)appDidBecomeActive:(NSNotification *)notification {
NSLog(@"did become active notification");
}


- (void)appWillEnterForeground:(NSNotification *)notification {
NSLog(@"will enter foreground notification");
}


- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"view will appear");
}


- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"view did appear");
}

在启动时,输出如下:

2013-04-07 09:31:06.505 myapp[15459:11303] view did load
2013-04-07 09:31:06.507 myapp[15459:11303] view will appear
2013-04-07 09:31:06.511 myapp[15459:11303] app did become active
2013-04-07 09:31:06.512 myapp[15459:11303] did become active notification
2013-04-07 09:31:06.517 myapp[15459:11303] view did appear

输入背景,然后重新输入前景:

2013-04-07 09:32:05.923 myapp[15459:11303] app will enter foreground
2013-04-07 09:32:05.924 myapp[15459:11303] will enter foreground notification
2013-04-07 09:32:05.925 myapp[15459:11303] app did become active
2013-04-07 09:32:05.926 myapp[15459:11303] did become active notification

我认为注册 UIApplicationWillEnterForeground 通知是有风险的,因为您最终可能会有多个控制器对该通知作出响应。无法保证在接收通知时这些控制器仍然可见。

下面是我所做的: 我强制调用 viewDidAppear 在活动控制器直接从应用程序的代理 did BecomeActive 方法:

将下面的代码添加到 - (void)applicationDidBecomeActive:(UIApplication *)application

UIViewController *activeController = window.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
activeController = [(UINavigationController*)window.rootViewController topViewController];
}
[activeController viewDidAppear:NO];

尝试将其添加到 AppDepate 应用程序 WillEnterForeground 中。

func applicationWillEnterForeground(_ application: UIApplication) {
// makes viewWillAppear run
self.window?.rootViewController?.beginAppearanceTransition(true, animated: false)
self.window?.rootViewController?.endAppearanceTransition()
}

根据苹果的文档:

(void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated;

描述:
告诉子控制器其外观即将更改。 如果要实现自定义容器控制器,请使用此方法告诉子级它的视图即将到 出现或消失不要直接调用 ABC0、 ABC1、 ABC2或 viewDidDisappear:.

(void)endAppearanceTransition;

描述:

告诉子控制器其外观已更改。 如果要实现自定义容器控制器,请使用此方法告诉子级视图转换已完成。

示例代码:

(void)applicationDidEnterBackground:(UIApplication *)application
{


[self.window.rootViewController beginAppearanceTransition: NO animated: NO];  // I commented this line


[self.window.rootViewController endAppearanceTransition]; // I commented this line


}

问题: 我怎么修好的?

Ans : 我在应用程序中发现了这段代码,这段代码让我的应用程序没有收到任何 ViewWillAppear 的通知。

Swift 3.0 + + 版本

viewDidLoad中,在通知中心注册,以便从后台操作中听到这个打开的声音

NotificationCenter.default.addObserver(self, selector:#selector(doSomething), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
        

然后添加这个函数并执行所需的操作

func doSomething(){
//...
}

最后,添加这个函数来清理视图控制器被销毁时的通知观察器。

deinit {
NotificationCenter.default.removeObserver(self)
}

Swift 4.2版本

viewDidLoad中注册 NotificationCenter,当应用程序从后台返回时会得到通知

NotificationCenter.default.addObserver(self, selector: #selector(doSomething), name: UIApplication.willEnterForegroundNotification, object: nil)

实现应该调用的方法。

@objc private func doSomething() {
// Do whatever you want, for example update your view.
}

一旦 ViewController被销毁,你可以移除观察者。这只需要在 iOS9和 macOS 10.11之下

deinit {
NotificationCenter.default.removeObserver(self)
}