261 votes

Erreur "Classe inconnue <MyClass> dans le fichier Interface Builder" au moment de l'exécution.

Même si Interface Builder est conscient d'une MyClass J'obtiens une erreur lors du démarrage de l'application.

Cela se produit lorsque MyClass fait partie d'une bibliothèque, et ne se produit pas si je compile la classe directement dans l'application cible.

0 votes

Comment se connecter à la bibliothèque ?

0 votes

J'utilise un sous-projet dépendant, et j'ai fait un drag'n'drop depuis les produits du sous-projet Xcode dans la phase de construction "Link Binary With Library" de ma cible actuelle.

0 votes

Si la classe est issue de CocoaPods, ceci pourrait aider github.com/CocoaPods/CocoaPods/issues/491 .

224voto

jhoule Points 1806

Malgré le " Classe inconnue MyClass dans le fichier Interface Builder. "Ce problème n'a rien à voir avec Interface Builder, mais plutôt avec le linker, qui ne lie pas une classe parce qu'aucun code ne l'utilise directement.

Lorsque les données .nib (compilées à partir du .xib) sont chargées au moment de l'exécution, MyClass est référencé en utilisant une chaîne, mais l'éditeur de liens n'analyse pas la fonctionnalité du code, seulement son existence, donc il ne le sait pas. Comme aucun autre fichier source ne fait référence à cette classe, l'éditeur de liens l'optimise pour qu'elle n'existe pas lors de la création de l'exécutable. Ainsi, lorsque le code d'Apple essaie de charger une telle classe, il ne peut pas trouver le code qui lui est associé et affiche l'avertissement.

Par défaut, les cibles Objective-C auront -all_load -ObjC activé par défaut, ce qui permet de conserver tous les symboles. Mais j'avais commencé avec une cible C++, et je n'avais pas cela. Néanmoins, j'ai trouvé un moyen de contourner ce problème, qui maintient l'agressivité de l'éditeur de liens.

Le hack que j'utilisais à l'origine était d'ajouter une routine statique vide comme :

+(void)_keepAtLinkTime;

qui ne fait rien, mais que j'appellerais une fois, comme :

int main( int argc, char** argv )
{
   [MyClass _keepAtLinkTime];
   // Your code.
}

Cela forcerait le linker à garder la classe entière, et l'erreur disparaîtrait.

Comme jlstrecker l'a fait remarquer dans les commentaires, nous n'avons pas vraiment besoin d'ajouter un _keepAtLinkTime méthode. Il suffit d'appeler une méthode existante, telle que :

   [MyClass class];

fait l'affaire (à condition de dériver d'un fichier NSObject ).

Bien entendu, vous pouvez appeler cette fonction à n'importe quel endroit de votre code. Je suppose que cela pourrait même être dans du code inaccessible. L'idée est de tromper l'éditeur de liens en lui faisant croire que MyClass est utilisé quelque part pour qu'il ne soit pas si agressif en l'optimisant.

Xcode 6.3.2 et Swift 1.2

Définition rapide de la vue. Assurez-vous de remplacer init(coder aDecoder: NSCoder) . Définition Objective-C du contrôleur de vue. Et, une plume dans un poirier.

Ajoutez le nom du module à l'inspecteur des détails de la Nib où vous choisissez votre classe.

2 votes

Les données .xib ne sont pas chargées au moment de l'exécution. Le compilateur de l'IB compile le xib en une nib ; c'est cette dernière qui est chargée au moment de l'exécution.

19 votes

Vous n'avez pas à modifier MyClass . Il suffit d'appeler une méthode dont il hérite NSObject comme +class .

10 votes

Bien qu'il n'y ait pas de Xcode 4 lorsque la question originale a été postée, ce qui suit semble toujours approprié. Dans Xcode 4, au lieu d'ajouter une méthode factice pour éliminer l'erreur, vous pouvez vérifier toutes les cibles nécessaires de l'élément MyClass.m dans la section Adhésion à la cible de l'inspecteur de fichiers.

184voto

Pat Points 1291

J'ai corrigé ce problème en suivant les indications de Laura, mais je n'ai pas eu besoin de recréer les fichiers.

  • Avec XCode 4, dans l'onglet Navigateur de projet Sélectionnez le fichier .m qui contient la classe qui fait l'objet de la plainte.

  • Allez dans Affichage->Utilitaires->Afficher l'inspecteur de fichiers.
    (ceci montrera le Inspecteur de fichiers à droite, avec les informations sur le fichier .m)

  • Ouvrez le Membres ciblés et assurez-vous que votre cible est sélectionnée pour ce fichier .m.

Lorsque j'ai ajouté mon fichier .m à mon projet, il n'a pas été ajouté à ma cible par défaut pour une raison quelconque, ce qui a entraîné l'erreur que vous avez mentionnée.

0 votes

Il est vrai que parfois, l'erreur de l'éditeur de liens est due au fait que votre fichier n'a tout simplement pas été compilé dans votre cible en premier lieu. Ce que vous décrivez est le moyen de contrôler la ou les cibles auxquelles un fichier est associé. Malheureusement, mon fichier faisait déjà partie de ma cible, mais j'ai quand même eu un problème de liaison. Cela est probablement dû au fait que ma bibliothèque est en C++ (par opposition à Objective-C), qui a des drapeaux de liaison par défaut différents (voir les messages d'Alasdair Allan et de Sijo ci-dessus).

5 votes

Cette suggestion a fonctionné pour moi, bien que de manière légèrement différente, puisque la case à cocher "Target Membership" était déjà cochée. Je l'ai décochée et reconstruit, mais le message d'erreur a changé pour indiquer mon nouveau nom de classe. En revérifiant la case et en reconstruisant, tout fonctionne maintenant. Beaucoup plus facile que de supprimer les fichiers de cache !

0 votes

Excellente solution via l'interface utilisateur de Xcode. @electromaggot, Xcode peut être confus lorsque vous ajoutez des classes manuellement, donc vous pouvez avoir besoin d'ajouter plus d'un fichier.

73voto

Alasdair Allan Points 1773

Cela n'a rien à voir avec Interface Builder. Ce qui se passe ici, c'est que les symboles ne sont pas chargés depuis votre bibliothèque statique par Xcode. Pour résoudre ce problème, vous devez ajouter l'option -all_load -ObjC aux drapeaux Other Linker Flags clé les paramètres de construction du projet (et éventuellement de la cible).

Puisqu'Objective-C ne génère qu'un seul symbole par classe, nous devons forcer le linker à charger également les membres de la classe en utilisant le flag -ObjC, et nous devons également forcer l'inclusion de tous nos objets de notre bibliothèque statique en ajoutant l'attribut -all_load de l'éditeur de liens. Si vous ignorez ces drapeaux, tôt ou tard, vous rencontrerez l'erreur suivante unrecognized selector ou obtenir d'autres exceptions comme celle que vous avez observée ici.

6 votes

J'ai trouvé que juste le -ObjC Le drapeau seul a réglé le problème dans mon cas.

5 votes

@Kekoa c'est parce que votre version de Xcode (LLVM) est plus récente que celle utilisée par l'auteur de cette réponse. De nos jours, l'utilisation de -ObjC est suffisant pour résoudre le problème.

0 votes

Ça m'a seulement aidé. Pendant la compilation, il a montré des problèmes liés au framework qui ont été résolus une fois que j'ai importé tous les frameworks.

20voto

Subbu Points 876

Allez dans "ProjectName" , cliquez dessus , et ensuite allez dans l'onglet "Build phases" , et ensuite cliquez sur "compile sources" , et ensuite cliquez sur le bouton "+" , une fenêtre apparaitra , choisissez le fichier "MyClass.m" et ensuite cliquez sur "add" ,

Construisez le projet et exécutez-le, le problème sera sûrement résolu.

0 votes

Oui, je n'avais pas coché TOUTES les cases des cibles que je voulais ajouter à mes classes nouvellement importées. Merci !

0 votes

Oui ! Mon fichier VC était absent du projet cible.

19voto

Ignacio Pascual Points 523

C'est un problème de cache de Xcode4, supprimez simplement tous les dossiers sous /Users/votre_utilisateur/Bibliothèque/Application Support/iPhone Simulator/4.3/Applications/

Aussi, si vous avez le même problème en testant sur votre iPhone, supprimez l'ancienne application avant de la lancer...

Bonne chance. Pascual

8 votes

Dans les paramètres de construction du projet, vous devez ajouter les drapeaux "-all_load -ObjC" à la clé "Other Linker Flags". Ce n'est pas un problème spécifique à Xcode 4, et en fait, cela n'a généralement rien à voir avec Interface Builder non plus.

0 votes

Cette solution a déjà été suggérée en janvier 2010 (voir ci-dessus).

6 votes

Oui, la façon la plus simple de le faire est d'ouvrir le simulateur iOS et de choisir dans le menu "Réinitialiser le contenu et les paramètres".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X