J'écris une application et je dois changer la vue si l'utilisateur regarde l'application tout en parlant au téléphone.
J'ai implémenté la méthode suivante:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"viewWillAppear:");
_sv.frame = CGRectMake(0.0, 0.0, 320.0, self.view.bounds.size.height);
}
Mais elle n'est pas appelée lorsque l'application revient au premier plan.
Je sais que je peux implémenter:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarFrameChanged:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
mais je ne veux pas faire ça. Je préfère de loin mettre toutes mes informations de mise en page dans la méthode viewWillAppear: et laisser cela gérer tous les scénarios possibles.
J'ai même essayé d'appeler viewWillAppear: from applicationWillEnterForeground :, mais je n'arrive pas à identifier qui est le contrôleur de vue actuel à ce moment-là.
Quelqu'un connaît-il la bonne façon de gérer cela? Je suis sûr que je manque une solution évidente.
ios
objective-c
iphone
viewwillappear
Philip Walton
la source
la source
applicationWillEnterForeground:
pour déterminer quand votre application est à nouveau entrée dans l'état actif.isMemberOfClass
ouisKindOfClass
, selon vos besoins.Réponses:
La méthode
viewWillAppear
doit être prise dans le contexte de ce qui se passe dans votre propre application, et non dans le contexte de votre application placée au premier plan lorsque vous y revenez à partir d'une autre application.En d'autres termes, si quelqu'un regarde une autre application ou prend un appel téléphonique, puis revient à votre application qui était auparavant en arrière-plan, votre UIViewController qui était déjà visible lorsque vous avez quitté votre application ne s'en soucie pas pour ainsi dire - en ce qui le concerne, il n'a jamais disparu et il est toujours visible - et ainsi
viewWillAppear
ne s'appelle pas.Je vous déconseille d'appeler
viewWillAppear
vous-même - cela a une signification spécifique que vous ne devriez pas renverser! Une refactorisation que vous pouvez effectuer pour obtenir le même effet peut être la suivante:Ensuite, vous déclenchez également à
doMyLayoutStuff
partir de la notification appropriée:Il n'y a aucun moyen prêt à l'emploi de dire quel est le UIViewController «actuel» au fait. Mais vous pouvez trouver des moyens de contourner cela, par exemple, il existe des méthodes déléguées de UINavigationController pour savoir quand un UIViewController y est présenté. Vous pouvez utiliser une telle chose pour suivre le dernier UIViewController qui a été présenté.
Mettre à jour
Si vous mettez en page les interfaces utilisateur avec les masques de redimensionnement automatique appropriés sur les différents bits, parfois vous n'avez même pas besoin de gérer la mise en page `` manuelle '' de votre interface utilisateur - elle est simplement traitée ...
la source
self.navigationController.topViewController
le fournit effectivement, ou du moins celui sur le dessus de la pile, qui serait le en cours si ce code est en train de tirer sur le thread principal dans un contrôleur de vue. (Cela pourrait être faux, je n'ai pas beaucoup joué avec, mais cela semble fonctionner.)appDelegate.rootViewController
fonctionnera aussi, mais il pourrait renvoyer unUINavigationController
, et vous en aurez besoin.topViewController
comme le dit @MatthewFrederick.Rapide
Réponse courte
Utilisez
NotificationCenter
plutôt un observateur queviewWillAppear
.Longue réponse
Pour savoir quand une application revient de l'arrière-plan, utilisez
NotificationCenter
plutôt un observateur queviewWillAppear
. Voici un exemple de projet qui montre quels événements se produisent quand. (Ceci est une adaptation de cette réponse Objective-C .)Au premier démarrage de l'application, l'ordre de sortie est le suivant:
Après avoir appuyé sur le bouton d'accueil, puis remis l'application au premier plan, l'ordre de sortie est le suivant:
Donc , si vous essayez d'utiliser à l' origine
viewWillAppear
puisUIApplication.willEnterForegroundNotification
est probablement ce que vous voulez.Remarque
Depuis iOS 9 et versions ultérieures, vous n'avez pas besoin de supprimer l'observateur. La documentation indique:
la source
Utilisez Notification Center dans la
viewDidLoad:
méthode de votre ViewController pour appeler une méthode et à partir de là, faites ce que vous étiez censé faire dans votreviewWillAppear:
méthode. AppelerviewWillAppear:
directement n'est pas une bonne option.la source
dealloc
méthode.viewWillAppear:animated:
, l'une des méthodes les plus déroutantes des SDK iOS à mon avis, ne doit jamais être invoquée dans une telle situation, c'est-à-dire le changement d'application. Cette méthode n'est invoquée qu'en fonction de la relation entre la vue du contrôleur de vue et la fenêtre de l'application , c'est-à-dire que le message n'est envoyé à un contrôleur de vue que si sa vue apparaît sur la fenêtre de l'application, pas sur l'écran.Lorsque votre application passe en arrière-plan, les vues les plus hautes de la fenêtre d'application ne sont évidemment plus visibles pour l'utilisateur. Dans la perspective de votre fenêtre d'application, cependant, ce sont toujours les vues les plus hautes et donc elles n'ont pas disparu de la fenêtre. Ces vues ont plutôt disparu car la fenêtre de l'application a disparu. Ils n'ont pas disparu parce qu'ils ont disparu de la fenêtre.
Par conséquent, lorsque l'utilisateur revient à votre application, elles semblent évidemment apparaître à l'écran, car la fenêtre apparaît à nouveau. Mais du point de vue de la fenêtre, ils n'ont pas du tout disparu. Par conséquent, les contrôleurs de vue ne reçoivent jamais le
viewWillAppear:animated
message.la source
Swift 4.2 / 5
la source
En essayant de le rendre aussi simple que possible, voir le code ci-dessous:
la source