Étant nouveau sur Cocoa, j'ai quelques problèmes avec Interface Builder
, UIViewController
et amis.
J'ai une sous-classe UIViewController
avec un UIView
défini dans un xib, et avec la sortie de vue du contrôleur connectée à la vue. Le "propriétaire du fichier" de xib est défini comme sous-classe myViewcontroller .
Dans cette seule instance, le code suivant pour charger le contrôleur/vue (à partir du contrôleur de vue principal) ne fonctionne pas comme prévu:
if ( self.myViewController == nil )
{
self.myViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:nil];
}
[self.navigationController
pushViewController:self.myViewController animated:YES];
Dans les méthodes de MyViewController, j'ai placé des points d'arrêt et des messages de journal pour voir ce qui se passe:
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
NSLog(@"initWithNibName\n");
}
return self;
}
-(void)viewDidLoad {
[super viewDidLoad];
NSLog(@"viewDidLoad\n");
}
Résultat attend
Tous les deux -initWithNibName
et -viewDidLoad
les méthodes sont appelées et la vue de myViewController s'affiche.
Résultat observé
Seulement -initWithNibName
est appelé, la vue n'est pas affichée.
Ai-je raté quelque chose? Quelqu'un peut-il recommander quelque chose à vérifier? (En particulier dans l'outil merveilleusement opaque Interface Builder).
Ok, j'ai une réponse partielle - peut-être que les gourous peuvent en expliquer davantage. Le problème est:
[self.navigationController pushViewController:myViewController animated:YES];
En y regardant de plus près, dans ce cas self.navigationController
est nul - donc le message Push ne va nulle part.
Au lieu de cela, si j'envoie:
[self.view addSubview:self.myViewController.view];
Ensuite, la vue apparaît et -viewDidLoad
est appelé.
Je ne sais pas vraiment pourquoi self.navigationController
n'est pas défini dans cette instance - la seule chose à laquelle je peux penser est que self
est une sous-classe de UIViewController
plutôt que UITableViewController
(où le pushViewController
le code vient).
De plus, laisser silencieusement les messages aller à zéro semble être une mauvaise idée, bien que ces réponses disent le contraire. Voir aussi ma question ici .
Édition finale:
Dans les commentaires ci-dessous, j'ai réalisé que la fonction d'affichage que je recherchais réellement (étant donné que monViewController est modal) est:
[self presentModalViewController:myViewController animated:YES];
Merci à tous pour leurs réponses utiles.
RE: SOLUTION TROUVÉE !!!!!
En effet, cela semble être une solution de travail, mais la vraie astuce n'est pas de définir le view.hidden
propriété à NO, ce qui fait que la vue se charge depuis le fichier nib est l'appel de UIViewController's
méthode de vue, la vue n'est réellement chargée à partir de la nib que lorsque la méthode de vue est appelée pour la première fois.
En ce sens, un simple [viewController view]
le message forcerait la vue à se charger à partir du fichier nib.
SOLUTION TROUVÉE !!!!!
Même quelque chose d'aussi inoffensif que cela rend possible l'appel de méthode viewDidLoad
.
Insérez ce droit après alloc initWithNibName
viewController.view.hidden = NO; //calls viewDidLoad
Il est possible que vous n'ayez pas lié le supposé ViewController
dans main.storyboard
Du Identity Inspector
Au class
personnalisé que vous avez créé. Vous pourrez peut-être naviguer vers ce contrôleur à partir d'autres contrôleurs de vue via des séquences, mais aucun des viewDidLoad()
, viewWillAppear()
etc. ne sera exécuté.
Utilisez simplement
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
//Your Code here
}
au lieu de la méthode viewDidLoad.
assurez-vous que la sortie de la vue dans le propriétaire du fichier (votre sous-classe viewController) est connectée à la vue réelle (c'est-à-dire le canevas 480X320 que vous voyez sur votre écran que vous utilisez pour construire votre interface utilisateur)
Une autre raison, assez évidente rétrospectivement: si viewController.view
est défini dans le code, puis l'événement viewDidLoad ne se déclenchera pas.
Cela ressemble à un problème de capitalisation pour moi. Vous faites référence à la classe MyViewController
au lieu de la propriété myViewController
dans l'appel à pushViewController.
Vérifiez votre journal d'exécution pour les erreurs. Il est presque certain que la NIB ne se charge pas et il devrait y avoir une erreur à cet effet. La cause la plus probable est le fait de ne pas le mettre dans le bundle. Regardez dans votre phase de build "Copy Resources" et assurez-vous que le XIB est réellement copié. Construisez pour le simulateur, descendez dans le répertoire de construction et assurez-vous que la NIB est dans le bundle .app.