Lorsque mon application est chargée pour la première fois, j'ai défini la propriété rootViewController
de ma UIWindow
sur controllerA
.
Parfois, au cours de mon application, j'ai choisi de changer rootViewController
en controllerB
.
Le problème est que, parfois, lorsque je fais une transition inversée dans controllerB
, je vois la vue de controllerA
derrière celle-ci. Pour une raison quelconque, cette vue n'est pas supprimée. Ce qui est encore plus inquiétant, c’est qu’après avoir défini la méthode rootViewController
à controllerB
, controllerA
, la méthode dealloc
ne soit jamais déclenchée.
J'ai essayé de supprimer les sous-vues de UIWindow
manuellement avant de passer à controllerB
, ce qui résout le problème de voir les vues de controllerA
en arrière-plan, mais le dealloc de controllerA
n'est jamais appelé. Que se passe t-il ici????
Les documents sur les pommes disent:
Le contrôleur de vue racine fournit la vue du contenu de la fenêtre. L'affectation d'un contrôleur de vue à cette propriété (par programme ou à l'aide d'Interface Builder) installe la vue du contrôleur de vue en tant que vue de contenu de la fenêtre. Si la fenêtre possède une hiérarchie de vues existante, les anciennes vues sont supprimées avant les nouvelles.
METTRE À JOUR
Voici le code de mon AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self showControllerA];
[self.window makeKeyAndVisible];
return YES;
}
- (void)showControllerA
{
ControllerA* a = [ControllerA new];
self.window.rootViewController = a;
}
- (void) showControllerB {
ControllerB* b = [ControllerB new];
self.window.rootViewController = b;
}
Il s'avère qu'il y a deux problèmes distincts. 1) J'avais un cycle de conservation dans le contrôleur A, de sorte qu'il n'était jamais désalloué. Deuxièmement, pour changer le contrôleur de vue racine, vous devez d'abord supprimer les sous-vues de Windows (même si la documentation suggère le contraire).
Le problème peut provenir de votre implémentation de ControllerA ou ControllerB, ils peuvent conserver «auto» dans le code afin que ARC puisse automatiquement désaffecter ViewController. Pouvez-vous poster votre implémentation ControllerA et ControllerB.
var loginNavigationController: OnBoardViewController?{
willSet{
if newValue == nil {
loginNavigationController?.view.removeFromSuperview()
}
}
}
loginNavigationController = nil
C'est le bug d'Apple, nous supposons que ViewControllerA est l'actuel rootViewController:
// ViewControllerA.m
- (void)buttonClick {
[self dismissViewControllerAnimated:YES completion:^{
// [((AppDelegate *)[[UIApplication sharedApplication] delegate]) resetRoot]; // OK
}];
[((AppDelegate *)[[UIApplication sharedApplication] delegate]) resetRoot]; // ViewControllerA's view will not dealloc
}
// AppDelegate.m
- (void)resetRoot {
ViewControllerB *controller = [[ViewControllerB alloc] init];
self.window.rootViewController = controller;
}
Si vous réinitialisez rootViewController de la fenêtre avec ce code, la vue de ViewControllerA ne sera jamais traitée.