web-dev-qa-db-fra.com

le storyboard instantiateViewControllerWithIdentifier ne définit pas IBOutlets

J'utilise le storyboard instantiateViewControllerWithIdentifier: et je remarque que tous les IBOutlets que j'ai câblés sont toujours nuls. Cependant, la IBActions j'ai câblé le travail. La vue et le contrôleur sont liés (c'est-à-dire controller.view n'est pas nul), et si je montre la vue, cela affiche ce que j'attends.

Qu'est-ce que je rate?

Voici ma configuration:

  1. J'ai un contrôleur de vue défini dans mon storyboard. Je lui ai donné un identifiant identique à celui que j'ai utilisé lors de l'appel de instantiateViewControllerWithIdentifier:
  2. J'ai configuré le propriétaire de la vue en cliquant sur le contrôleur de vue (juste sous Premier répondant) et sous l'inspecteur d'identité, définissez la classe personnalisée sur le même nom que la classe à laquelle je souhaite connecter la vue.
  3. Ensuite, j'ouvre l'éditeur adjoint et je contrôle les éléments de l'interface utilisateur glissés pour créer les variables IBOutlets et IBActions.
36
BlueFish

La vue semble être initialisée correctement uniquement après avoir été accédée en premier. Le problème s'en va quand on appelle

[self presentViewController:vc animated:NO completion:nil];

ou plus simplement

[vc view];
67
Stefan Henze

[Utilisez-moi comme mauvais exemple]

Peut-être pas une bonne idée après tout, ça marche mais ça viole le chargement normal rendant l’app instable ^ _ ^.
Je laisserai la réponse ici au cas où quelqu'un d'autre voudrait savoir si vous le faites.


J'avais le même problème, mais le composant personnalisé que j'ai conçu n'est pas chargé via presentViewController (chargement en surimpression dans la vue précédente)

Vous pouvez simplement appeler

myViewController.loadView() // Swift

[myViewController loadView] // Obj-C

5
Cesar

Les gens ont expliqué comment charger la vue (dont vous ne devriez jamais utiliser (loadView()); voici donc un moyen de vérifier si votre vue est déjà chargée.

J'ai rencontré le problème car j'avais une propriété avec un observateur didSet pour mettre à jour l'interface utilisateur, ce qui ne fonctionne évidemment pas si les sorties ne sont pas encore définies. Voici donc un exemple de code permettant de la contourner:

var name: String? {
    didSet {
        updateNameLabel()
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    updateNameLabel()
}

func updateRoomLabel() {
    guard isViewLoaded() else {
        return
    }
    [...]
}

Alors maintenant, lorsque vous affichez les points de vente sont mis à jour, mais aussi chaque fois que vous mettez à jour la propriété 

0
hashier

Les prises sont établies avec le codage de valeur de clé, vous pouvez l'insérer dans votre sous-classe de contrôleur de vue:

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath {
    [super setValue:value forKeyPath:keyPath];
}

- (void)setValue:(id)value forKey:(NSString *)key {
    [super setValue:value forKeyPath:key];
}

Et mettez un point d'arrêt sur les deux appels à super.

Dans le débogueur, je voudrais essayer:

  1. En comparant 'soi-même' au contrôleur de vue, vous pensez que vous appliquez les points de vente. Peut-être que votre story-board a un second contrôleur de vue auquel vous ne vous attendez pas. Quand vous avez dit que vous avez créé un propriétaire, j'ai pensé que c'était une terminologie étrange. Avez-vous fait glisser l'un des objets de cube pour représenter votre contrôleur de vue en plus de la représentation déjà présente?

  2. Comparez [self valueForKey: key] ou [self valueForKeyPath: keyPath] ou juste [self outletName] avec la valeur transmise après l'appel jusqu'à super. Vous avez peut-être un passeur qui ne fait pas ce que vous voulez. J'ai vu une erreur comme celle-ci se produire à quelques reprises où les gens ont un exutoire pour un objet avec un nom tel que "prénom" puis une action avec le sélecteur "setFirstName:". Cela confond le codage de la valeur de la clé et vous vous retrouvez avec setFirstName: être appelé pendant le chargement de la pointe avec l'intention d'établir la sortie, mais le paramètre de configuration de la sortie est implémenté en tant que méthode d'action, de sorte que la sortie n'est jamais définie.

0
Jon Hess

Si l'objet auquel vous créez un lien est une entité de niveau supérieur dans la scène, tel qu'un ArrayController, la référence doit être forte (pas faible!) Car elle n'est pas conservée par la hiérarchie des vues. Une référence faible peut causer un problème comme celui que vous décrivez.

Regardez ici pour plus d'informations: Les IBOutlets doivent-ils être forts ou faibles sous ARC?

0
zgchurch

La définition du cadre pour ViewController instancié semble définir les IBOutlets.

ex:

DemoViewController *demoVC = [[self storyboard] instantiateViewControllerWithIdentifier:@"demoVC"];
demoVC.frame = self.view.frame; //or CGRectMake(0, 0, 1015, 604);

Cela initialiserait les IBOutlets de DemoViewController tels que Label, TextField, Button, Table, etc.

J'espère que cela t'aides.

0
Sushma Satish