web-dev-qa-db-fra.com

ViewDidAppear n'est pas appelé lors de l'ouverture de l'application en arrière-plan

J'ai un contrôleur de vue dans lequel ma valeur est 0 (étiquette) et lorsque j'ouvre ce contrôleur de vue à partir d'un autre ViewController j'ai réglé viewDidAppear sur la valeur 20 de l'étiquette. Cela fonctionne bien, mais lorsque je ferme mon application et que je l'ouvre à nouveau, mais la valeur ne change pas, car viewDidLoad, viewDidAppear et viewWillAppear rien n'est appelé. Comment puis-je appeler lorsque j'ouvre mon application? Dois-je faire quelque chose de applicationDidBecomeActive?

164
Zohaib

Curieux de connaître la séquence exacte des événements, j'ai instrumenté une application comme suit: (@Zohaib, vous pouvez utiliser le code NSNotificationCenter ci-dessous pour répondre à votre question).

// 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");
}

Au lancement, la sortie ressemble à ceci:

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

Entrez l'arrière-plan puis ré-entrez au premier plan:

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
303
lara

en utilisant Objective-C

Vous devez enregistrer un UIApplicationWillEnterForegroundNotification dans votre méthode ViewController's viewDidLoad et chaque fois que l'application revient de l'arrière-plan, vous pouvez faire ce que vous voulez dans la méthode enregistrée pour la notification. ViewController 'viewWillAppear ou viewDidAppear ne sera pas appelé lorsque l'application reviendra de l'arrière-plan à l'avant-plan.

-(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.
}

N'oubliez pas de désenregistrer la notification pour laquelle vous êtes enregistré.

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

Note Si vous enregistrez votre viewController pour UIApplicationDidBecomeActiveNotification, votre méthode sera appelée à chaque fois que votre application devient active. Il est déconseillé d'enregistrer viewController pour cette notification. .

en utilisant Swift

Pour ajouter observateur, vous pouvez utiliser le code suivant

 override func viewDidLoad() {
    super.viewDidLoad()

     NSNotificationCenter.defaultCenter().addObserver(self, selector:"doYourStuff", name:
     UIApplicationWillEnterForegroundNotification, object: nil)
 }

 func doYourStuff(){
     // your code
 }

Pour supprimer l'observateur, vous pouvez utiliser la fonction deinit de Swift.

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}
130
nsgulliver

Version Swift 3.0 ++

Dans votre viewDidLoad, enregistrez-vous dans le centre de notification pour écouter cette action ouverte à partir de l'arrière-plan.

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

Ajoutez ensuite cette fonction et effectuez l'action requise.

func doSomething(){
    //...
}

Enfin, ajoutez cette fonction pour nettoyer l’observateur de notification lorsque votre contrôleur de vue est détruit.

deinit {
    NotificationCenter.default.removeObserver(self)
}
42
Fangming

Swift 4.2. version

Inscrivez-vous auprès de NotificationCenter dans viewDidLoad pour être averti lorsque l'application revient de l'arrière-plan

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

Implémentez la méthode à appeler.

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

Vous pouvez supprimer l'observateur une fois que la ViewController est détruite. Ceci n'est requis que sous iOS9 et macOS 10.11

deinit {
    NotificationCenter.default.removeObserver(self)
}
6
gebirgsbärbel

Je pense que s’inscrire à la notification UIApplicationWillEnterForegroundNotification est risqué car il est possible que plusieurs contrôleurs réagissent à cette notification. Rien ne garantit que ces contrôleurs sont toujours visibles lors de la réception de la notification.

Voici ce que je fais: Je force l'appel de viewDidAppear sur le contrôleur actif directement depuis la méthode didBecomeActive du délégué de l'application:

Ajoutez le code ci-dessous à - (void)applicationDidBecomeActive:(UIApplication *)application

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

Demandez à votre contrôleur de vue de s’enregistrer pour la notification UIApplicationWillEnterForegroundNotification et réagissez en conséquence.

3
andreagiavatto

essayez d'ajouter ceci dans AppDelegate applicationWillEnterForeground.

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

Selon la documentation d'Apple:

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

Description:
Indique à un contrôleur enfant que son apparence est sur le point de changer. Si vous implémentez un contrôleur de conteneur personnalisé, utilisez cette méthode pour indiquer à l'enfant que ses vues sont sur le point de apparaître ou disparaître. Ne pas invoquer viewWillAppear:, viewWillDisappear:, viewDidAppear: ou viewDidDisappear: directement).

(void)endAppearanceTransition;

Description:

Indique à un contrôleur enfant que son apparence a changé. Si vous implémentez un contrôleur de conteneur personnalisé, utilisez cette méthode pour indiquer à l'enfant que la transition de vue est terminée.

Exemple de code:

(void)applicationDidEnterBackground:(UIApplication *)application
{

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

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

}

Question: Comment j'ai corrigé?

Ans: J'ai trouvé ce morceau de lignes en application. Cela a rendu mon application ne recevant aucune notification ViewWillAppear. Quand j'ai commenté ces lignes ça marche très bien.

2
Lakshmi