IBOutlet est nul, mais il est connecté en storyboard, Swift

Utiliser Swift 1.1 et Xcode 6.2.

J’ai un UIStoryboard contenant une sous-classe UIViewController unique et personnalisée. Sur celle-ci, j’ai une connexion @IBOutlet de type UIView partir de ce contrôleur vers une sous-classe UIView du storyboard. J’ai également des débouchés 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 assuré que je connectais les sockets dans Interface Builder.

Pensées :

  • Est-il possible que, parce que j’utilise une sous-classe d’une sous-classe, quelque chose perturbe l’initialisation? Je ne remplace pas les initialiseurs
  • awakeFromNib: n’est pas appelé pour une raison quelconque
  • Peut-être qu’il ne se connecte pas aux sous-vues sur les sous-vues

Les choses que j’ai essayées:

  • Correspondant @IBOutlet types d’élément @IBOutlet et storyboard exactement (au lieu de UIView )
  • Supprimer une propriété et un sharepoint vente et les rappend

Figure a

Figure A *

Figure B

Figure B

* Le code masqué de la Figure A est le suivant:

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

Je vous remercie.

En général, cela se produit car 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 vue lorsque quelque chose lui envoie le message de view . Le système le fait quand il est temps de mettre la hiérarchie de vue à l’écran, ce qui se produit après des choses comme prepareForSegue:sender: et viewWillAppear: sont retournés.

Comme 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 en disant self.view .

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

Avez-vous instancié votre contrôleur de vue depuis un Storyboard ou un NIB ou l’avez-vous instancié directement via un initialiseur?

Si vous instanciez votre classe directement avec l’initialiseur, les sorties ne seront pas connectées. Interface Builder crée des instances personnalisées de vos classes et code ces instances dans des NIB et des Storyboards pour un décodage répété. Il ne définit pas les classes elles-mêmes. Si cela était votre problème, il vous suffit de changer le code où vous créez votre contrôleur pour utiliser les méthodes sur UIStoryboard ou UINib.

Le storyboard ne reconnaissait plus d’interface utilisateur que j’y ai ajouté. Au moment de l’exécution, toutes les références étaient nulles. J’ai donc effacé mon dossier de données dérivé, puis ces connexions ont fonctionné à nouveau.

Dans mon cas, cela s’est produit parce que je remplace la méthode loadView dans ma sous-classe ViewController, mais j’ai oublié d’append [super loadView]

 -(void)loadView { // blank } 

Lorsque vous remplacez la méthode loadView , il est de votre responsabilité de lancer vos sous-vues. Comme vous le remplacez, les vues du générateur d’interface n’ont pas la possibilité d’être converties en objects cacao et les points de vente restnt donc nuls.

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

Ou appelez simplement

 [super loadView]; 

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

Cela m’arrivait avec ma cellule de vue de collection personnalisée. Il s’est avéré que je devais remplacer ma méthode registerClassforReuseIdentifier par registerNib. Cela a réglé pour moi.

Vous pouvez appeler controller.view pour forcer le chargement de la vue pour initialiser les IBOutlets, vous pourrez alors atsortingbuer 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 } } 

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

 class XYZViewController: UINavigationController { } 

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

Xcode ne prend pas en compte cette erreur, la classe semble bien se construire, et les fonctions telles que viewDidLoad , viewWillAppear , etc. Mais aucun des IBOutlet n’est connecté.

Changer la déclaration à

 class XYZViewController: UIViewController { } 

réparé complètement.

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

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 lancez votre ViewController. Surtout quand vous utilisez Swift (il n’y a presque rien dans l’éditeur lorsque vous créez un fichier de classe)

En utilisant simplement init() partir de la super classe ne peut pas initier quelque chose que vous avez travaillé avec storyboard. Donc, ce que vous devez faire, c’est changer l’initialisation du ViewController. Remplacez let XXViewController = XXViewController() par let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController Ceci indique au programme d’aller sur le storyboard trouver XXViewController et lance tous les IBOutlet dans votre storyboard.

J’espère que cette aide ~ GL

Pour Swift 3.

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

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

Autre cas:

Vos points de vente ne seront pas définis tant que la vue du contrôleur de vue n’est pas réellement instanciée, ce qui dans votre cas se produit probablement peu de temps après initWithNibName: bundle: à quel point ils seront toujours nuls. Toute configuration impliquant ces points de vente doit se produire dans la méthode -viewDidLoad de votre contrôleur de vue.

Pour moi, j’avais la même erreur sur un storyboard localisé, un élément avait été ajouté dans certains parameters régionaux et pas dans un autre, donc j’avais une référence nulle pour cet élément quand je passais à la locale manquante, je devais supprimer la localisation (redondante) pour ce storyboard en utilisant https://stackoverflow.com/a/42256341/1356559 .

Vous devez d’abord charger la hiérarchie de la vue pour instancier les sockets dans le storyboard. Pour cela, vous pouvez appeler manuellement les méthodes loadView ou loadViewIfNeeded.

Pour moi, cela se produisait car 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 le super.loadView() . Donc, l’ajout de ce problème a résolu pour moi.

Code fixe :

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

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 que les noms de fichiers reflétaient le nom de la classe, tout allait bien!

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

En avoir un de plus …

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

Vous pouvez valider si la vue is est chargée.

 if isViewLoaded && view.window != nil { //self.annotationOptionsView. } 
  1. sélectionner les fichiers de contrôleurs de vue .h et .m
  2. supprimer la référence de ces fichiers
  3. rajoutez les fichiers dans votre arbre de projet
  4. ouvrir le storyboard, éventuellement reconstruire le projet

Accidentellement, j’ai sous- AVPlayerViewController mon contrôleur de vue avec AVPlayerViewController au lieu de UIViewController . En le relisant à UIViewController choses reviennent normalement. Cela devrait aider.

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

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

 override var nibName 

et

 override var nibBundle 

méthodes.

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

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

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

Vérifiez si vous avez des points de vente manquants ou déconnectés.

entrer la description de l'image ici

Si vous avez deux main.storyboards et que vous apportez des modifications à la mauvaise, cela peut arriver. Cela peut se produire chaque fois que vous connectez un sharepoint vente à un storyboard fondé.

Si vous instanciez un view controller par programmation. 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.

Dans mon cas, l’application a commencé à tomber tout à coup. Le débogage a révélé que tous les points de vente étaient nil au moment de viewDidLoad() .

Mon application utilise toujours les nibs (pas les storyboards) pour la plupart des contrôleurs de vue. Tout était en place, tous les points de vente étaient 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 certaines raisons semble fonctionner aussi longtemps que le .xib est nommé de la même façon que la classe du contrôleur de vue (pas sûr de savoir comment cela fonctionne, cependant. Nous init(nibName:bundle:) pas init(nibName:bundle:) avec des arguments nil, ou redéfinir init() pour le faire soi- self comme c’est généralement suggéré …).

J’ai donc essayé d’appeler explicitement

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

… seulement pour être accueilli avec l’erreur d’exception à l’exécution:

*** Application de terminaison en raison d’une exception non capturée ‘NSInternalInconsistencyException’, raison: ‘Impossible de charger la NIB dans un bundle:’ NSBundle (chargé) ‘avec le nom’ MYCustomViewController ”

Et puis , je l’ai vu:

La case à cocher “Adhésion à la cible” du fichier .xib n’était pas cochée.


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

Apple a certainement besoin de proposer un format de fichier de projet plus compatible avec la GDS.