iOS: comportement addSubview différent entre iOS 4.3 et 5.0

lors du encoding dans iOS 4.3 avant, j'ai trouvé tout en ajoutant une vue de controller de vue à une autre vue avec [superview addSubView:controller.view] , l'instance du controller ne recevra pas le message -viewWillAppear/viewDidAppear , que j'ai trouvé le même problème dans certains threads débordement de stack. Après cela, j'appelle manuellement -viewWillAppear/-viewDidAppear selon les besoins.

mais, après la mise à niveau vers iOS 5.0 , un comportement fringant de UIView s'est produit. Enfin, j'ai trouvé que dans iOS 5, le [superview addSubView:controller.view] , va envoyer un message -viewWillAppear/-viewDidAppear à l'instance du controller automatiquement, plus mes appels manuellement, il y a deux messages dupliqués chaque fois que le controller action son comportement .

et j'ai également trouvé un problème similaire: iOS 5: -viewWillAppear n'est pas appelé après avoir rejeté le modal dans l'iPad

Maintenant, le problème est, après la search de documents Apple, je n'ai pas trouvé de document explicite pour diff sur ces questions. Je me request même si c'est un comportement de cycle de vie de vue garanti dans iOS 5.0.

Quelqu'un fixe-t-il des problèmes similaires ou trouve-t-il des directives sur ces différences? parce que je veux exécuter mon application à la fois dans 4.x & 5.x iOS

Dans iOS 4, vous avez dû appeler manuellement -viewWillAppear , -viewWillDisappear , etc. lors de l'ajout ou de la suppression d'une vue de votre hiérarchie de vue. Ceux-ci sont appelés automatiquement dans iOS 5 si la vue est ajoutée ou supprimée de la hiérarchie des windows . Heureusement, iOS 5 dispose d'une méthode dans UIViewController que vous pouvez replace pour revenir au fonctionnement de iOS 4. Ajoutez simplement ceci à votre UIViewController :

 -(BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers { return NO; } 

C'est probablement la solution la plus simple tant que vous soutenez à la fois iOS 4 et iOS 5. Une fois que vous supprimez le support pour iOS 4, vous pouvez envisager de modifier votre code pour utiliser la nouvelle approche lors de l'échange de vues.

Modifier 5 février 2012

Apparemment, cette fonction nécessite que le controller de vue enfant soit ajouté au controller de la vue principale à l'aide de la addChildViewController: . Cette méthode n'existe pas dans iOS4, vous devez donc faire quelque chose comme ceci:

  if ([self respondsToSelector:@selector(addChildViewController:)] ) { [self addChildViewController:childViewController]; } 

Merci à tous ceux qui m'ont corrigé à ce sujet.

Cela peut ne pas être une réponse à ce que vous voulez, mais j'ai eu le même genre de problème.

Dans mon cas, lorsque j'ai ajouté la vue d'un controller de vue à la vue d'un autre controller de vue en tant que sous-vue, la sous-vue a été reçue par viewWillAppear uniquement dans iOS 5.0 et non iOS 4.X.

J'ai donc ajouté une mauvaise condition.

 [self.view addSubview:self.viewController.view]; if ([[[UIDevice currentDevice] systemVersion] compare:@"5.0"] == NSOrderedAscending) { [self.viewController viewWillAppear:animated]; } 

Depuis iOS 5.0, Apple propose un moyen d'implémenter des controllers de vue de conteneur personnalisés tels que UINavigationController ou UITabController . Je pense que ce changement affecte quand viewWillAppear est appelé.

Ce problème peut être résolu si nous utilisons -[UIViewController addChildViewController:] .

Les réponses ci-dessus un peu incomplètes. Supposons que vous avez 2 controllers de vue, ControllerA et ControllerB.

ControllerA.view est déjà ajouté à la window (il s'agit du parent) et vous souhaitez append ControllerB.view en tant que sous-vue de ControllerA.

Si vous n'ajoutez pas ControllerB en tant qu'enfant de ControllerA en premier, automatiquementForwardAppearanceAndRotationMethodsToChildViewControllers sera ignoré et vous serez toujours appelé par iOS5, ce qui signifie que vous appellerez deux fois les callbacks du controller de vue.

Exemple dans ControllerA:

 - (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers { return NO; } - (void)viewDidLoad { [super viewDidLoad]; self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil]; [self.view addSubview:self.controllerB.view]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.controllerB viewWillAppear:animated]; } 

Dans ControllerB NSLogging dans viewWillAppear:

 - (void)viewWillAppear:(BOOL)animated { NSLog("@ControllerB will appear"); } 

Cela se traduira par iOS5 affichant uniquement ce message NSLog deux fois. c'est-à-dire que vous êtes automatiquementForwardAppearanceAndRotationMethodsToChildViewControllers a été ignoré.

Pour résoudre ce problème, vous devez append controllerB en tant qu'enfant du controller a.

De return dans la class de ControllerA:

 - (void)viewDidLoad { [super viewDidLoad]; self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil]; if ([self respondsToSelector:@selector(addChildViewController:)]) [self addChildViewController:self.controllerB]; [self.view addSubview:self.controllerB.view]; } 

Cela fonctionnera maintenant comme prévu dans iOS4 et iOS5 sans recourir à l'horrible hack de vérifier les strings de version iOS, mais plutôt de vérifier si la fonction que nous recherchons est disponible.

J'espère que cela t'aides.

C'est le comportement d'iOS5:
viewWillAppear, viewDidAppear, … sont exécutées automatiquement après addSubView: pour iOS5.
Donc, pour iOS5 pas besoin d'exécuter manuellement ces methods comme besoin pour iOS <5.0.

Le correctif peut être:

 if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) { ...execute viewWillAppear or other } 

Par cette méthode, vous savez qui vous utilisez et mettez la condition si elle est inférieure à 5.0 ou autre

[[UIDevice currentDevice] systemVersion]

view{Will,Did}Appear , view{Will,Did}Disappear sont des fonctions sur View Controllers et non des vues. Ces fonctions sont appelées par des controllers de vue fournis par le SDK qui sont supposés gérer d' autres controllers de vue, par exemple UITabBarController , UINavigationBarController .

Si vous gérez vous-même des controllers de sous-vue, vous devez les appeler explicitement (et dans le bon ordre – bien que vous ayez une très bonne raison de le faire). Une vue modale ne recevant pas ces appels lors du rejet d'une vue modale est simplement parce qu'il n'y a personne pour l'appeler. Encapsuler le controller de vue racine dans un UINavigationController (et masquer la barre de navigation si vous le souhaitez), puis ouvrez un controller de vue modale. Lors de son rejet, ou de pop, viewWillAppear sera appelé.

Après avoir examiné toutes les preuves, je pense que la meilleure chose à faire est de ne PAS utiliser viewDidAppear etc pour les vues qui sont affectées par ce bogue ios 4 / ios 5. Au lieu de cela, créez une class personnalisée (comme viewDidAppearCustom) et appelez-la vous-même. De cette façon, vous pouvez garantir que Apple ne changera pas le sdk à nouveau et vous gâcher. Il y a un super blog qui couvre ce problème ici:

http://gamesfromwithin.com/view-controller-notification-changes-on-ios5