web-dev-qa-db-fra.com

IBOutlet est nul, mais il est connecté dans le storyboard, Swift

Utiliser Swift 1.1 et Xcode 6.2.

J'ai un tableau UIStory contenant une sous-classe singulière et personnalisée UIViewController. Sur celui-ci, j'ai une connexion @IBOutlet de type UIView depuis ce contrôleur vers une UIViewsous-classe sur le storyboard. J'ai également des sorties similaires pour les sous-vues de cette vue. Voir la figure A.

Mais au moment de l'exécution, ces propriétés sont nulles (figure B). Même si j'ai la certitude d'avoir connecté les prises dans Interface Builder.

Pensées :

  • Est-il possible que, parce que j'utilise une sous-classe d'une sous-classe, quelque chose se gâte avec l'initialisation? Je ne prévois aucun initialiseur
  • awakeFromNib: n'est pas appelé pour une raison quelconque
  • Peut-être qu'il ne se connecte pas aux sous-vues sur les sous-vues

Ce que j'ai essayé:

  • Correspondance parfaite entre les types d'élément @IBOutlet et de storyboard (au lieu de UIView)
  • Supprimer une propriété et un point de vente et les rajouter

Figure A

Figure A *

Figure B

Figure B

* Le code masqué dans Figure A est:

@IBOutlet private var annotationOptionsView: UIView!
@IBOutlet private var arrivingLeavingSwitch: UISegmentedControl!

Je vous remercie.

86
Stefan Arambasich

Le story-board ne reconnaissait pas d'autres éléments de l'interface utilisateur que j'y ai ajoutés. Au moment de l'exécution, toutes les références étaient nulles. J'ai donc effacé mon dossier de données dérivées, puis ces connexions ont à nouveau fonctionné.

14
Stefan Arambasich

Cela se produit généralement parce que votre contrôleur de vue n'a pas encore chargé sa hiérarchie de vues. Un contrôleur de vue charge uniquement sa hiérarchie de vues lorsque quelque chose lui envoie le message view. Le système procède ainsi lorsqu'il est temps de placer la hiérarchie de vues à l'écran, ce qui se produit après le retour d'éléments tels que prepareForSegue:sender: et viewWillAppear:.

Puisque votre VC n'a pas encore chargé sa hiérarchie de vues, vos points de vente sont toujours nuls.

Vous pouvez forcer le VC à charger sa hiérarchie de vues en disant _ = self.view.

125
rob mayoff

Avez-vous essayé d'exécuter Product> Clean. Résolu un problème très similaire pour moi.

25
ThottChief

Avez-vous instancié votre contrôleur de vue à partir d'un Storyboard ou d'une carte NIB, ou l'avez-vous instancié directement via un initialiseur?

Si vous avez instancié votre classe directement avec l'initialiseur, les prises ne seront pas connectées. Interface Builder crée des instances personnalisées de vos classes et les code dans des NIB et des Storyboards pour un décodage répété. Il ne définit pas les classes elles-mêmes. Si tel était votre problème, il vous suffit de modifier le code dans lequel vous créez votre contrôleur pour utiliser plutôt les méthodes sur UIStoryboard, ou UINib.

19
Jon Hess

Dans mon cas, cela s'est produit parce que j'ai surchargé la méthode loadView dans ma sous-classe ViewController, mais j'ai oublié d'ajouter [super loadView].

-(void)loadView {
// blank
}

Lorsque vous substituez la méthode loadView, il vous incombe de lancer vos sous-vues. Étant donné que vous la remplacez, les vues du constructeur d’interface n’ont pas la possibilité de convertir des objets en cacao et les points de vente restent nuls.

Si vous implémentez loadView dans votre sous-classe de contrôleur de vue, il vous incombe alors de charger les éléments d'interface utilisateur à partir de storyboard/xib dans le code.

Ou appelez simplement

[super loadView];

Pour que la super-classe ait la chance de charger le storyboard/xib dans le code.

10
zinnuree

Cela m'arrivait avec ma cellule d'affichage de collection personnalisée. Il s'avère que j'ai dû remplacer ma méthode registerClassforReuseIdentifier par registerNib. Cela a réglé le problème pour moi.

8
rounak

Vous pouvez appeler controller.view pour forcer le chargement de la vue afin d'initialiser les IBOutlets, vous pourrez ensuite affecter les valeurs.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "identifier") {
        let controller = segue.destinationViewController as! YourController
        let _ = controller.view //force to load the view to initialize the IBOutlets

        controller.your_IBOutlet_property = xxx
        ...
        controller.delegate = self
    }
}
6
zsong

Pour moi, cela s’est produit lorsque j’ai accidentellement déclaré la classe de mon contrôleur de vue:

class XYZViewController: UINavigationController {
}

(c.-à-d. en tant que UINavigationController pas un UIViewController).

Xcode ne comprend pas cette erreur, la classe semble bien fonctionner et remplacer les fonctions telles que viewDidLoad, viewWillAppear, etc. fonctionnent correctement. Mais aucun des IBOutlets ne se connecte.

Changer la déclaration en

class XYZViewController: UIViewController {
}

résolu complètement.

6
HughHughTeotl

Cela m’est arrivé parce que j’ai accidentellement instancié directement mon contrôleur de vue au lieu de l’instancier dans le scénarimage. Si vous instanciez directement via MyViewController(), les prises ne seront pas connectées.

5
Eric Conner

Je rencontre ce problème récemment! Voici ma pensée ... Le problème ne concerne pas votre storyboard ni aucun problème de lien. Il s'agit de la façon dont vous démarrez votre ViewController. Surtout lorsque vous utilisez Swift (il n'y a presque rien dans l'éditeur lorsque vous créez un fichier de classe) 

En utilisant simplement la init() de la classe supérieure, vous ne pouvez rien initier avec lequel vous avez travaillé avec le scénario. Vous devez donc modifier l’initialisation du ViewController. Remplacez let XXViewController = XXViewController() Par let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController Cela indique au programme d'aller dans le storyboard rechercher XXViewController et de lancer tous les IBOutlet de votre storyboard.

J'espère que cette aide ~ GL

4
user3882355

Pour Swift 3.

func configureView() {
    let _  = self.view
}
3
prog_24

Solution de travail à 100% pour la création de ViewControllers à partir de XIB sans StoryBoards

  1. Créer une classe CustomViewController: UIViewController
  2. Créer une vue CustomViewControllerView.xib
  3. Dans CustomViewControllerView.xib dans Interface Builder, sélectionnez Placeholders -> Propriétaire du fichier.
  4. Dans "Inspecteur d'attributs", définissez Class sur CustomViewController.
  5. Dans "Inspecteur de connexions", connectez "vue" à la vue de niveau supérieur de xib (assurez-vous que la classe de la vue de niveau supérieur ne pointe pas sur CustomViewController)
  6. Dans "Inspecteur de connexions", connectez d'autres prises (si nécessaire/existant)
  7. Créer une instance de CustomViewController dans le contrôleur de vue parent/le délégué App

7.1.

// creating instance
let controller = CustomViewController()

7.2.

// connecting view/xib with controller instance
let bundle = Bundle(for: type(of: controller))
bundle.loadNibNamed("CustomViewControllerView", owner: controller, options: nil)

7.3.

// get/set outlets
controller.labelOutlet.text = "title"
controller.imageOutlet.image = UIImage(named: "image1")
1
Roman M

Pour moi, la même erreur se produisait sur un storyboard localisé: un élément avait été ajouté dans certaines langues et pas dans l'autre. ce storyboard en utilisant https://stackoverflow.com/a/42256341/1356559 .

1
Amr Lotfy

Encore un autre cas que je viens de rencontrer. J'ai changé le nom de ma classe pour UIViewController, mais j'ai oublié de changer le nom du fichier .xib où l'interface a été construite. 

Une fois que j'ai compris cela et fait en sorte que les noms de fichiers reflètent le nom de la classe, tout était bien!

J'espère que cela aide quelqu'un.

1
Brian Trzupek

Vous devez d'abord charger la hiérarchie des vues afin d'instancier les points de vente dans le storyboard. Pour cela, vous pouvez appeler manuellement les méthodes loadView ou loadViewIfNeeded.

1
maven25

Autre cas:

Vos prises ne seront pas configurées tant que la vue du contrôleur de vue ne sera pas instanciée, ce qui dans votre cas se produira probablement peu de temps après initWithNibName: bundle: - à ce stade, elles seront toujours nil. Toute configuration impliquant ces sorties doit avoir lieu dans la méthode -viewDidLoad de votre contrôleur de vue.

1

Vérifiez votre connexion IBOutlet si elle est connectée au propriétaire du fichier ou à la vue ..__ Il pourrait y avoir des erreurs.

1
Ahd Radwan

Si vous instanciez view controller par programme. Ensuite, essayez de le créer comme ci-dessous

let initialVC = self.storyboard?.instantiateViewController(withIdentifier: "InitialVC") as! InitialVC

au lieu de directement

let initialVC = InitialVC()

Cela a fonctionné pour moi.

1
Vinoth Vino

Pour moi, cela se bloquait parce que containerView était nul. 

Voici mon code avec Crash .

@IBOutlet private var containerView: UIView!  // Connected to Storyboard
override open func loadView() {
    containerView.addSubview(anotherView)
}

La chose manquante appelait la super.loadView(). Donc, l'ajouter a résolu le problème pour moi.

Code fixe :

@IBOutlet private var containerView: UIView!
override open func loadView() {
    super.loadView()
    containerView.addSubview(anotherView)
}
1
BLC

J'ai encore un ...

Si vous avez une classe personnalisée pour un UITableViewCell mais oubliez de spécifier Custom dans le style de la cellule.

1
Phantom59

Vous pouvez valider si la vue est chargée.

if isViewLoaded && view.window != nil {
 //self.annotationOptionsView.
}
1
A. Trejo
  1. sélectionner les fichiers de contrôleur .h et .m
  2. supprimer la référence de ces fichiers
  3. rajoutez les fichiers à votre arborescence de projet
  4. ouvrir le story-board, éventuellement reconstruire le projet
0
Sandip Patel - SM

J'ai eu le même problème après avoir copié une classe (liée à une xib) pour la réutiliser avec une autre classe viewcontroller (liée à un storyboard) .

override var nibName

et

override var nibBundle

méthodes.

Après les avoir enlevés, mes points de vente ont commencé à fonctionner.

0
smukamuka

Vérifiez si vous avez des prises manquantes ou déconnectées.

 enter image description here

Accidentellement J'ai sous-classé mon contrôleur de vue avec AVPlayerViewController au lieu de UIViewController. En le rejouant à UIViewController, les choses reviennent à la normale. Cela devrait aider.

Aucun nettoyage de construction (normal et complet), la suppression des dossiers de données dérivés et la fermeture de Xcode ont fonctionné pour moi.

0
Hemang

Je vois que vous utilisez ViewController !? dans la classe ViewController vous devez utiliser -viewDidLoad, pas -awakeFromNib, -awakeFromNib utiliser pour UIView classe

0
EvGeniy Ilyin

Dans mon cas, l'application s'est effondrée soudainement . Le débogage de celle-ci a révélé que toutes les prises étaient encore nil au moment de viewDidLoad().

Mon application utilise toujours nibs (pas de storyboards) pour la plupart des contrôleurs de vue. Tout était en place, tous les points de vente câblés correctement. J'ai vérifié deux fois.

Nous instancions généralement nos contrôleurs de vue comme

let newVC = MYCustomViewController()

... qui, pour une raison quelconque, semble fonctionner tant que le fichier .xib porte le même nom que la classe du contrôleur de vue (vous ne savez pas comment cela fonctionne. Nous sommes pas en train d'appeler init(nibName:bundle:) avec des arguments nil ou de remplacer init() pour le faire sur self comme il est généralement suggéré ...).

Alors j'ai essayé d'appeler explicitement

 let newVC = MYCustomViewController(nibName: "MYCustomViewController", bundle: .main)

... uniquement pour être accueilli avec l'erreur d'exception d'exécution: 

*** Application de terminaison en raison d'une exception non interceptée 'NSInternalInconsistencyException', raison: 'Impossible de charger la NIB dans le lot:' NSBundle </ Users/nicolasmiari/Bibliothèque/Développeur/CoreSimulator/Devices/3DA3CF21-108D-498F-9649-C4FC9E3C1A8D/data /Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app> (chargé) 'avec le nom' MYCustomViewController ''

Et alors, je l'ai vu:

La case à cocher "Adhésion à la cible" du fichier .xib a été décochée.


Cela doit être arrivé lors de la résolution d'un des conflits de fusion fréquents concernant le fichier de projet Xcode.

Apple certainement doit proposer un format de fichier de projet plus convivial.

0
Nicolas Miari

J'avais un problème similaire lorsque j'avais précédemment ajouté register (_: forCellReuseIdentifier :) pour la cellule personnalisée après avoir défini l'identifiant dans le storyboard. Avait ce code dans la fonction viewDidLoad (). Une fois que je l'ai enlevé, cela a bien fonctionné.

0
Gthoma2

Si vous avez deux main.storyboards et que vous apportez des modifications au mauvais, cela peut arriver. Cela peut arriver chaque fois que vous connectez un point de vente à partir d'une storyboard non instanciée. 

0
ScottyBlades