首页 文章

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

提问于
浏览
149

我有一个View Controller,其值为0(标签),当我从另一个 ViewController 打开View Controller时,我已将 viewDidAppear 设置为标签上的值20 . 它工作正常,但当我关闭我的应用程序,而不是再次打开我的应用程序,但值不会更改,因为 viewDidLoadviewDidAppearviewWillAppear 没有被调用 . 我打开应用程序时如何打电话 . 我是否必须做 applicationDidBecomeActive 的任何事情?

8 回答

  • 121

    Using Objective-C

    您应该在 ViewControllerviewDidLoad 方法中注册 UIApplicationWillEnterForegroundNotification ,每当应用程序从后台返回时,您可以在注册通知的方法中执行任何操作 . 当应用程序从后台返回到前台时,将不会调用 ViewControllerviewWillAppearviewDidAppear .

    -(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];
    }
    

    Note 如果您为 UIApplicationDidBecomeActiveNotification 注册 viewController ,则每次应用程序生效时都会调用您的方法,不建议为此通知注册 viewController .

    Using Swift

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

    override func viewDidLoad() {
        super.viewDidLoad()
    
         NSNotificationCenter.defaultCenter().addObserver(self, selector:"doYourStuff", name:
         UIApplicationWillEnterForegroundNotification, object: nil)
     }
    
     func doYourStuff(){
         // your code
     }
    

    要删除观察者,您可以使用swift的deinit函数 .

    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  • 2

    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)
    }
    
  • 1

    尝试在AppDelegate applicationWillEnterForeground中添加它 .

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

    根据Apple的文档:

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

    Description:
    告诉儿童控制器它的外观即将改变 . 如果要实现自定义容器控制器,请使用此方法告诉子项其视图即将为 appear or disappear . Do not invoke viewWillAppear:, viewWillDisappear:, viewDidAppear:, or viewDidDisappear: directly .

    (void)endAppearanceTransition;
    

    Description:

    告诉儿童控制器它的外观已经改变 . 如果要实现自定义容器控制器,请使用此方法告诉子项视图转换已完成 .

    Sample code:

    (void)applicationDidEnterBackground:(UIApplication *)application
    {
    
        [self.window.rootViewController beginAppearanceTransition: NO animated: NO];  // I commented this line
    
        [self.window.rootViewController endAppearanceTransition]; // I commented this line
    
    }
    

    问题: How I fixed?

    Ans :我在申请中发现了这条线 . 这条线使我的应用程序无法收到任何ViewWillAppear通知 . When I commented these lines it's working fine .

  • 0

    Swift 3.0版

    viewDidLoad 中,在通知中心注册以收听从后台操作打开的内容

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

    然后添加此功能并执行所需的操作

    func doSomething(){
        //...
    }
    

    最后添加此函数以在视图控制器被销毁时清理通知观察器 .

    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
  • 36

    对事件的确切顺序感到好奇,我按如下方式对应用程序进行了检测:(@ 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
    
  • 3

    我认为注册UIApplicationWillEnterForegroundNotification是有风险的,因为你最终可能会有多个控制器对该通知作出反应 . 收到通知后,这些控制器仍然可见,这些都没有任何保证 .

    这是我的工作:我直接从App的委托didBecomeActive方法强制在活动控制器上调用viewDidAppear:

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

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

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

相关问题