UIViewController créé avec initWithNibName: bundle: ou via un IBOutlet se comportent différemment

StackOverflow https://stackoverflow.com/questions/2257124

Question

J'ai trouvé un comportement étrange, et je voudrais expliquer ce que l'affirmation que je fais qui ne va pas.

Dans une classe AppDelegate d'un projet WindowBased fraîchement créé, je suis l'ajout d'un UIViewController à la fenêtre.
Je peux le faire de deux façons différentes:
 - avec un IBOutlet. Dans IB, je simplement instanciés un UIViewController, mis à sa classe TestViewController et connecté (scénario A du code).
 - la création du UIViewController avec le code (scénario B).

    - (void)applicationDidFinishLaunching:(UIApplication *)application {    

#define USE_IBOUTLET YES // Comment this line to switch to scenario B

#ifdef USE_IBOUTLET
    // Scenario A

    [window addSubview:theTestViewController.view];
    [window makeKeyAndVisible];
#endif


#ifndef USE_IBOUTLET
    // Scenario B

    TestViewController *theTestViewControllerProgrammatically;

    theTestViewControllerProgrammatically = [[TestViewController alloc] initWithNibName:nil bundle:nil];

    // According to Apple: "It is a good idea to set the view's frame before adding it to a window.", so let's do it
    [theTestViewControllerProgrammatically.view setFrame:[[UIScreen mainScreen] applicationFrame]];

    [window addSubview:theTestViewControllerProgrammatically.view];

    [window makeKeyAndVisible];
#endif
}

Comme je ne fais pas de personnalisation de l'objet dans IB, je devrais avoir le même comportement dans les deux scénarios.

Scénario A, en utilisant le IBOutlet fonctionne comme prévu.
Mais le scénario B présente les problèmes suivants:
 - La vue est pas à la bonne position (20 pixels à haute et couverte par la barre d'état)
.  - La vue ne redimensionne pas correctement (par exemple, essayez de basculer l'appel dans la barre d'état)

Pourquoi?

archive Zip du projet ici si vous voulez reproduire le problème: http : //dl.dropbox.com/u/1899122/code/ProtoWindowBasedStrangeness.zip

Était-ce utile?

La solution

Cela va paraître vraiment stupide après mes réponses de longue haleine, mais le problème que vous rencontrez est simple à fixer (programatically).

Cette ligne:

[theTestViewController.view setFrame:[[UIScreen mainScreen] applicationFrame]];

devrait en fait être:

[theTestViewControllerProgrammaticaly setFrame:[[UIScreen mainScreen] applicationFrame]];

Vous établissiez le cadre du VC fixé par IB, non par celui que vous avez créé programatically.

Quoi qu'il en soit - il est intéressant de noter que tous mes commentaires appliquent toujours! Il y a encore quelques choses que vous aurez à faire si vous ne programme pas utiliser les objets du contrôleur de l'IB (par exemple, mise en place des éléments de la barre de navigation)

Paul

Autres conseils

J'ai eu un problème très semblable à vous que je dans Remarqué objets VC ne sont pas tous créés égaux! Le problème que je vais avoir est le réglage des éléments de la barre de navigation, je semble incapable de le faire lorsque le propriétaire du fichier est une vue objet contrôleur que j'instancier programatically. Il ne fonctionne que si j'UnArchive les objets du contrôleur de l'IB.

J'ai téléchargé votre projet et avait un jeu avec elle, et il m'a fait penser un peu plus sur ce qui pourrait se passer. Je pense que je peux apporter une réponse raisonnable, mais ne sais pas s'il y a une solution simple ...

Ce que je crois qui se passe est que Apple a créé ces objets de contrôleur dans IB qui sont un peu plus spécialisés. Une suggestion que cela pourrait être vrai est que les objets IB VC ont un attribut que vous pouvez définir qui n'a pas de propriété correspondant directement pour une classe UIViewController que je peux voir, si les objets du contrôleur de l'IB peuvent avoir des fonctionnalités supplémentaires que les sous-classes non-IB UIViewController ne peut pas profiter de. Étant donné que les objets dans un .xib sont des objets complets « lyophilisées », Apple peut avoir inclus tous les types d'attributs privés, nous ne pouvons pas voir ou utiliser dans leurs versions IB d'entre eux - cela peut avoir un effet sur la façon dont sont initialisés les objets .

Par exemple, dans votre MainWindow.xib, sélectionnez l'objet IB VC et vous pouvez définir des attributs sur elle de la palette Inspecteur, comme « Redimensionner View From NIB ». Si vous cochez cette non et re-exécuter votre application, vous verrez le VC apparaissent exactement comme il le fait dans le scénario B. Comme vous ne pouvez pas vérifier ce point lors du propriétaire du fichier attributs (même si elle est comme UIViewController ), vous ne parvenez pas à tirer profit de tout ce qui est fait par le contrôleur afin de vous donner le comportement que vous voulez.

Le résultat de ceci est que lorsque vous utilisez TestViewController.xib pour initialiser votre objet VC dans le code, aucun des attributs spécifiques de l'IB d'un VC sont fixés, donc une UIViewController de tourbière standard est créé, et tant de choses comme le « Resize Voir de NIB » attribut et la mise en place des éléments de navigation doivent être mis en œuvre vous.

Je ne l'ai pas encore trouvé un moyen de tirer parti de la fonctionnalité que les contrôleurs de vue de l'IB ont quand j'instancier les utiliser initWithNibName:bundle:nibBundle (je devine que c'est tous les trucs privé, nous ne pouvons pas accéder), mais nous espérons que cela pourrait avoir donné vous un point de départ ...

Bien sûr, je pourrais être complètement faux et que quelqu'un va me faire ressembler à un idiot!

Paul

Probablement dans le cas où B ce point de vue n'a pas connaissance de la présence d'une barre d'état. Vous devez redimensionner en conséquence et ajuster sa position pour prendre la barre d'état en compte. Cela se fait en changeant les propriétés cadre (taille) et les limites (emplacement) d'un UIView.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top