Catégories Objective-C dans la bibliothèque statique

153

Pouvez-vous me guider comment lier correctement la bibliothèque statique au projet iPhone. J'utilise le projet de bibliothèque statique ajouté au projet d'application en tant que dépendance directe (cible -> général -> dépendances directes) et tout fonctionne bien, mais les catégories. Une catégorie définie dans la bibliothèque statique ne fonctionne pas dans l'application.

Ma question est donc de savoir comment ajouter une bibliothèque statique avec certaines catégories dans un autre projet?

Et en général, quelles sont les meilleures pratiques à utiliser dans le code de projet d'application d'autres projets?

Vladimir
la source
1
eh bien, j'ai trouvé des réponses et il semble que cette question ait déjà été répondue ici (désolé, j'ai manqué stackoverflow.com/questions/932856/… )
Vladimir

Réponses:

228

Solution: à partir de Xcode 4.2, il vous suffit d'accéder à l'application qui relie la bibliothèque (pas la bibliothèque elle-même) et de cliquer sur le projet dans le navigateur de projet, de cliquer sur la cible de votre application, puis de créer les paramètres, puis de rechercher "Autre Linker Flags ", cliquez sur le bouton + et ajoutez" -ObjC ". "-all_load" et "-force_load" ne sont plus nécessaires.

Détails: J'ai trouvé des réponses sur divers forums, blogs et docs Apple. J'essaye maintenant de faire un bref résumé de mes recherches et expériences.

Le problème a été causé par (citation de Apple Q&R technique QA1490 https://developer.apple.com/library/content/qa/qa1490/_index.html ):

Objective-C ne définit pas les symboles de l'éditeur de liens pour chaque fonction (ou méthode, en Objective-C) - à la place, les symboles de l'éditeur de liens ne sont générés que pour chaque classe. Si vous étendez une classe préexistante avec des catégories, l'éditeur de liens ne sait pas associer le code objet de l'implémentation de la classe principale et l'implémentation de la catégorie. Cela empêche les objets créés dans l'application résultante de répondre à un sélecteur défini dans la catégorie.

Et leur solution:

Pour résoudre ce problème, la bibliothèque statique doit transmettre l'option -ObjC à l'éditeur de liens. Cet indicateur amène l'éditeur de liens à charger chaque fichier objet de la bibliothèque qui définit une classe ou une catégorie Objective-C. Bien que cette option se traduise généralement par un exécutable plus volumineux (en raison du code objet supplémentaire chargé dans l'application), elle permettra la création réussie de bibliothèques statiques Objective-C efficaces qui contiennent des catégories sur les classes existantes.

et il y a aussi des recommandations dans la FAQ sur le développement iPhone:

Comment lier toutes les classes Objective-C dans une bibliothèque statique? Définissez le paramètre de génération Other Linker Flags sur -ObjC.

et les descriptions des drapeaux:

- all_load Charge tous les membres des bibliothèques d'archives statiques.

- ObjC Charge tous les membres des bibliothèques d'archives statiques qui implémentent une classe ou une catégorie Objective-C.

- force_load (path_to_archive) Charge tous les membres de la bibliothèque d'archives statiques spécifiée. Remarque: -all_load force tous les membres de toutes les archives à être chargés. Cette option vous permet de cibler une archive spécifique.

* nous pouvons utiliser force_load pour réduire la taille binaire de l'application et pour éviter les conflits que all_load peut provoquer dans certains cas.

Oui, cela fonctionne avec les fichiers * .a ajoutés au projet. Pourtant, j'ai eu des problèmes avec le projet lib ajouté en tant que dépendance directe. Mais plus tard, j'ai découvert que c'était de ma faute - le projet de dépendance directe n'a peut-être pas été ajouté correctement. Lorsque je le supprime et que je le rajoute avec les étapes:

  1. Faites glisser et déposez le fichier de projet lib dans le projet d'application (ou ajoutez-le avec Projet-> Ajouter au projet…).
  2. Cliquez sur la flèche sur l'icône du projet lib - nom de fichier mylib.a affiché, faites glisser ce fichier mylib.a et déposez-le dans le groupe Target -> Link Binary With Library.
  3. Ouvrez les informations sur la cible dans la première page (Général) et ajoutez ma bibliothèque à la liste des dépendances

après cela, tout fonctionne bien. Le drapeau "-ObjC" était suffisant dans mon cas.

J'ai également été intéressé par l'idée du blog http://iphonedevelopmentexperiences.blogspot.com/2010/03/categories-in-static-library.html . L'auteur dit qu'il peut utiliser la catégorie de la lib sans définir l'option -all_load ou -ObjC. Il vient d'ajouter à la catégorie h / m les fichiers interface / implémentation de classe factice vide pour forcer l'éditeur de liens à utiliser ce fichier. Et oui, cette astuce fait l'affaire.

Mais l'auteur a également déclaré qu'il n'avait même pas instancié l'objet factice. Mm… Comme je l'ai trouvé, nous devrions explicitement appeler du code "réel" à partir d'un fichier de catégorie. Donc au moins la fonction de classe devrait être appelée. Et nous n'avons même pas besoin de cours factices. Une seule fonction c fait de même.

Donc, si nous écrivons les fichiers lib comme:

// mylib.h
void useMyLib();

@interface NSObject (Logger)
-(void)logSelf;
@end


// mylib.m
void useMyLib(){
    NSLog(@"do nothing, just for make mylib linked");
}


@implementation NSObject (Logger)
-(void)logSelf{
    NSLog(@"self is:%@", [self description]);
}
@end

et si nous appelons useMyLib (); n'importe où dans le projet App puis dans n'importe quelle classe, nous pouvons utiliser la méthode de catégorie logSelf;

[self logSelf];

Et plus de blogs sur le thème:

http://t-machine.org/index.php/2009/10/13/how-to-make-an-iphone-static-library-part-1/

http://blog.costan.us/2009/12/fat-iphone-static-libraries-device-and.html

Vladimir
la source
8
La note technique d'Apple semble avoir été modifiée depuis pour dire "Pour résoudre ce problème, la cible reliant la bibliothèque statique doit passer l'option -ObjC à l'éditeur de liens." ce qui est le contraire de ce qui est cité ci-dessus. Nous venons de confirmer que vous devez inclure lors de la liaison de l'application et non de la bibliothèque elle-même.
Ken Aspeslagh
Selon la documentation developer.apple.com/library/mac/#qa/qa1490/_index.html , nous devrions utiliser l'indicateur -all_load ou -force_load. Comme mentionné, l'éditeur de liens a un bogue dans l'application Mac 64 bits et l'application iPhone. "Important: pour les applications 64 bits et iPhone OS, il existe un bogue de l'éditeur de liens qui empêche -ObjC de charger des fichiers objets à partir de bibliothèques statiques qui ne contiennent que des catégories et aucune classe. La solution de contournement consiste à utiliser les indicateurs -all_load ou -force_load."
Robin
2
@Ken Aspelagh: Merci, j'ai eu le même problème. Les indicateurs -ObjC et -all_load doivent être ajoutés à l' application elle - même , pas à la bibliothèque.
titaniumdecoy
3
Excellente réponse, même si les nouveaux arrivants à cette question devraient noter qu'elle est désormais obsolète. Découvrez la réponse de tonklon stackoverflow.com/a/9224606/322748 (all_load / force_load ne sont plus nécessaires)
Jay Peyer
Je suis resté coincé sur ces choses pendant près d'une demi-heure et avec un essai et une erreur, je viens de le comprendre. De toute façon merci. Cette réponse vaut un +1 et vous l'avez !!!
Deepukjayan
118

La réponse de Vladimir est en fait plutôt bonne, cependant, j'aimerais vous donner plus de connaissances de base ici. Peut-être qu'un jour quelqu'un trouvera ma réponse et la trouvera utile.

Le compilateur transforme les fichiers source (.c, .cc, .cpp, .m) en fichiers objets (.o). Il existe un fichier objet par fichier source. Les fichiers objets contiennent des symboles, du code et des données. Les fichiers objets ne sont pas directement utilisables par le système d'exploitation.

Maintenant, lors de la construction d'une bibliothèque dynamique (.dylib), d'un framework, d'un bundle chargeable (.bundle) ou d'un exécutable binaire, ces fichiers objets sont liés entre eux par l'éditeur de liens pour produire quelque chose que le système d'exploitation considère comme "utilisable", par exemple quelque chose qu'il peut charger directement à une adresse mémoire spécifique.

Cependant lors de la construction d'une bibliothèque statique, tous ces fichiers objets sont simplement ajoutés à un gros fichier archive, d'où l'extension de bibliothèques statiques (.a pour archive). Ainsi, un fichier .a n'est rien qu'une archive de fichiers objet (.o). Pensez à une archive TAR ou à une archive ZIP sans compression. Il est simplement plus facile de copier un seul fichier .a que tout un tas de fichiers .o (similaire à Java, où vous regroupez les fichiers .class dans une archive .jar pour une distribution facile).

Lors de la liaison d'un binaire à une bibliothèque statique (= archive), l'éditeur de liens obtiendra une table de tous les symboles de l'archive et vérifiera lesquels de ces symboles sont référencés par les binaires. Seuls les fichiers objets contenant des symboles référencés sont effectivement chargés par l'éditeur de liens et sont pris en compte par le processus de liaison. Par exemple, si votre archive contient 50 fichiers objets, mais que seulement 20 contiennent des symboles utilisés par le binaire, seuls ces 20 sont chargés par l'éditeur de liens, les 30 autres sont entièrement ignorés dans le processus de liaison.

Cela fonctionne assez bien pour le code C et C ++, car ces langages essaient d'en faire autant que possible au moment de la compilation (bien que C ++ ait également des fonctionnalités d'exécution uniquement). Obj-C, cependant, est un autre type de langage. Obj-C dépend fortement des fonctionnalités d'exécution et de nombreuses fonctionnalités d'Obj-C sont en fait des fonctionnalités uniquement d'exécution. Les classes Obj-C ont en fait des symboles comparables aux fonctions C ou aux variables C globales (au moins dans le runtime Obj-C actuel). Un éditeur de liens peut voir si une classe est référencée ou non, afin de déterminer une classe en cours d'utilisation ou non. Si vous utilisez une classe à partir d'un fichier objet dans une bibliothèque statique, ce fichier objet sera chargé par l'éditeur de liens car l'éditeur de liens voit un symbole en cours d'utilisation. Les catégories sont une fonctionnalité uniquement à l'exécution, les catégories ne sont pas des symboles comme des classes ou des fonctions et cela signifie également qu'un éditeur de liens ne peut pas déterminer si une catégorie est utilisée ou non.

Si l'éditeur de liens charge un fichier objet contenant du code Obj-C, toutes les parties Obj-C de celui-ci font toujours partie de l'étape de liaison. Donc, si un fichier objet contenant des catégories est chargé parce que tout symbole de celui-ci est considéré comme "en cours d'utilisation" (que ce soit une classe, que ce soit une fonction, que ce soit une variable globale), les catégories sont également chargées et seront disponibles au moment de l'exécution . Pourtant, si le fichier objet lui-même n'est pas chargé, les catégories qu'il contient ne seront pas disponibles au moment de l'exécution. Un fichier objet contenant uniquement des catégories est jamais chargé , car il contient pas de symboles l'éditeur de liens ne jamais considérer « en usage ». Et c'est là tout le problème.

Plusieurs solutions ont été proposées et maintenant que vous savez comment tout cela joue ensemble, revoyons la solution proposée:

  1. Une solution consiste à ajouter -all_loadà l'appel de l'éditeur de liens. Que fera réellement cet indicateur de l'éditeur de liens? En fait, il indique à l'éditeur de liens ce qui suit: « Chargez tous les fichiers objets de toutes les archives, que vous voyiez un symbole en cours d'utilisation ou non .» Bien sûr, cela fonctionnera, mais cela peut aussi produire des binaires assez volumineux.

  2. Une autre solution consiste à ajouter -force_loadà l'appel de l'éditeur de liens en incluant le chemin d'accès à l'archive. Cet indicateur fonctionne exactement comme -all_load, mais uniquement pour l'archive spécifiée. Bien sûr, cela fonctionnera également.

  3. La solution la plus populaire consiste à ajouter -ObjCà l'appel de l'éditeur de liens. Que fera réellement cet indicateur de l'éditeur de liens? Cet indicateur indique à l'éditeur de liens " Chargez tous les fichiers objets de toutes les archives si vous voyez qu'ils contiennent du code Obj-C ". Et "tout code Obj-C" comprend des catégories. Cela fonctionnera également et ne forcera pas le chargement de fichiers objets ne contenant pas de code Obj-C (ceux-ci ne sont toujours chargés qu'à la demande).

  4. Une autre solution est le nouveau paramètre de construction Xcode Perform Single-Object Prelink. Que fera ce paramètre? Si cette option est activée, tous les fichiers objets (rappelez-vous, il y en a un par fichier source) sont fusionnés en un seul fichier objet (qui n'est pas une véritable liaison, d'où le nom PreLink ) et ce fichier objet unique (parfois également appelé "objet maître file ") est ensuite ajouté à l'archive. Si maintenant un symbole du fichier objet maître est considéré comme utilisé, le fichier objet maître entier est considéré comme utilisé et donc toutes les parties Objective-C de celui-ci sont toujours chargées. Et comme les classes sont des symboles normaux, il suffit d'utiliser une seule classe d'une telle bibliothèque statique pour obtenir également toutes les catégories.

  5. La solution finale est l'astuce que Vladimir a ajoutée à la toute fin de sa réponse. Placez un " faux symbole " dans n'importe quel fichier source ne déclarant que des catégories. Si vous souhaitez utiliser l'une des catégories au moment de l'exécution, assurez-vous de référencer d'une manière ou d'une autre le faux symbole au moment de la compilation, car cela entraîne le chargement du fichier objet par l'éditeur de liens et donc également de tout le code Obj-C qu'il contient. Par exemple, il peut s'agir d'une fonction avec un corps de fonction vide (qui ne fera rien lors de l'appel) ou d'une variable globale accessible (par exempleintune fois lu ou écrit, cela suffit). Contrairement à toutes les autres solutions ci-dessus, cette solution déplace le contrôle sur les catégories disponibles au moment de l'exécution vers le code compilé (s'il veut qu'elles soient liées et disponibles, il accède au symbole, sinon il n'accède pas au symbole et l'éditeur de liens ignorera il).

Ce sont tous des gens.

Oh, attendez, il y a encore une chose:
l'éditeur de liens a une option nommée -dead_strip. Que fait cette option? Si l'éditeur de liens décide de charger un fichier objet, tous les symboles du fichier objet font partie du binaire lié, qu'ils soient utilisés ou non. Par exemple, un fichier objet contient 100 fonctions, mais une seule d'entre elles est utilisée par le binaire, les 100 fonctions sont toujours ajoutées au binaire car les fichiers objets sont soit ajoutés dans leur ensemble, soit ils ne sont pas ajoutés du tout. L'ajout partiel d'un fichier objet n'est généralement pas pris en charge par les éditeurs de liens.

Cependant, si vous indiquez à l'éditeur de liens "dead strip", l'éditeur de liens ajoutera d'abord tous les fichiers objets au binaire, résoudra toutes les références et analysera enfin le binaire pour les symboles non utilisés (ou uniquement utilisés par d'autres symboles non utilisation). Tous les symboles qui ne sont pas utilisés sont ensuite supprimés dans le cadre de l'étape d'optimisation. Dans l'exemple ci-dessus, les 99 fonctions inutilisées sont à nouveau supprimées. Ceci est très utile si vous utilisez des options telles que -load_all, -force_loadou Perform Single-Object Prelinkparce que ces options peuvent facilement augmenter considérablement les tailles binaires dans certains cas et le décapage mort supprimera à nouveau le code et les données inutilisés.

Le décapage mort fonctionne très bien pour le code C (par exemple, les fonctions, les variables et les constantes inutilisées sont supprimées comme prévu) et cela fonctionne également assez bien pour C ++ (par exemple, les classes inutilisées sont supprimées). Ce n'est pas parfait, dans certains cas, certains symboles ne sont pas supprimés même si ce serait correct de les supprimer, mais dans la plupart des cas, cela fonctionne assez bien pour ces langues.

Et Obj-C? Oublie ça! Il n'y a pas de décapage mort pour Obj-C. Comme Obj-C est un langage à fonctionnalités d'exécution, le compilateur ne peut pas dire au moment de la compilation si un symbole est réellement utilisé ou non. Par exemple, une classe Obj-C n'est pas utilisée s'il n'y a pas de code la référençant directement, n'est-ce pas? Faux! Vous pouvez créer dynamiquement une chaîne contenant un nom de classe, demander un pointeur de classe pour ce nom et allouer dynamiquement la classe. Par exemple au lieu de

MyCoolClass * mcc = [[MyCoolClass alloc] init];

Je pourrais aussi écrire

NSString * cname = @"CoolClass";
NSString * cnameFull = [NSString stringWithFormat:@"My%@", cname];
Class mmcClass = NSClassFromString(cnameFull);
id mmc = [[mmcClass alloc] init];

Dans les deux cas, il mmcy a une référence à un objet de la classe «MyCoolClass», mais il n'y a aucune référence directe à cette classe dans le deuxième exemple de code (pas même le nom de classe sous forme de chaîne statique). Tout se passe uniquement au moment de l'exécution. Et c'est même si les classes sont en fait de vrais symboles. C'est encore pire pour les catégories, car ce ne sont même pas de vrais symboles.

Donc, si vous avez une bibliothèque statique avec des centaines d'objets, mais que la plupart de vos binaires n'en ont besoin que de quelques-uns, vous préférerez peut-être ne pas utiliser les solutions (1) à (4) ci-dessus. Sinon, vous vous retrouvez avec de très gros binaires contenant toutes ces classes, même si la plupart d'entre elles ne sont jamais utilisées. Pour les classes, vous n'avez généralement pas besoin de solution spéciale car les classes ont de vrais symboles et tant que vous les référencez directement (pas comme dans le deuxième exemple de code), l'éditeur de liens identifiera assez bien leur utilisation de lui-même. Pour les catégories, cependant, considérez la solution (5), car elle permet d'inclure uniquement les catégories dont vous avez vraiment besoin.

Par exemple, si vous voulez une catégorie pour NSData, par exemple en y ajoutant une méthode de compression / décompression, vous créez un fichier d'en-tête:

// NSData+Compress.h
@interface NSData (Compression)
    - (NSData *)compressedData;
    - (NSData *)decompressedData;
@end

void import_NSData_Compression ( );

et un dossier d'implémentation

// NSData+Compress
@implementation NSData (Compression)
    - (NSData *)compressedData 
    {
        // ... magic ...
    }

    - (NSData *)decompressedData
    {
        // ... magic ...
    }
@end

void import_NSData_Compression ( ) { }

Maintenant, assurez-vous simplement que n'importe où dans votre code import_NSData_Compression()est appelé. Peu importe où il est appelé ou à quelle fréquence il est appelé. En fait, il n'a pas vraiment besoin d'être appelé du tout, c'est suffisant si l'éditeur de liens le pense. Par exemple, vous pouvez mettre le code suivant n'importe où dans votre projet:

__attribute__((used)) static void importCategories ()
{
    import_NSData_Compression();
    // add more import calls here
}

Vous n'avez jamais besoin d'appeler importCategories()votre code, l'attribut fera croire au compilateur et à l'éditeur de liens qu'il est appelé, même si ce n'est pas le cas.

Et un dernier conseil:
si vous ajoutez -whyloadà l'appel de lien final, l'éditeur de liens imprimera dans le journal de construction quel fichier objet à partir de quelle bibliothèque il a chargé en raison du symbole utilisé. Il n'imprimera que le premier symbole considéré en cours d'utilisation, mais ce n'est pas nécessairement le seul symbole utilisé de ce fichier objet.

Mecki
la source
1
Merci d'avoir mentionné -whyload, essayer de déboguer pourquoi l'éditeur de liens fait quelque chose peut être assez difficile!
Ben S
Il y a une option Dead Code Strippingdans Build Settings>Linking. Est-ce le même que celui -dead_stripajouté Other Linker Flags?
Xiao
1
@Sean Oui, c'est pareil. Lisez simplement l '"Aide rapide" qui existe pour chaque paramètre de construction, la réponse est là: postimg.org/image/n7megftnr/full
Mecki
@Mecki Merci. J'ai essayé de m'en débarrasser -ObjC, alors j'ai essayé ton hack mais ça se plaint "import_NSString_jsonObject()", referenced from: importCategories() in main.o ld: symbol(s) not found. J'ai mis import_NSString_jsonObjectdans mon Framework intégré nommé Utility, et ajouter #import <Utility/Utility.h>avec une __attribute__déclaration à la fin de mon AppDelegate.h.
Xiao
@Sean Si l'éditeur de liens ne trouve pas le symbole, vous n'effectuez pas de liaison avec la bibliothèque statique qui contient le symbole. Le simple fait d'importer un fichier à partir d'un framework ne créera pas de lien Xcode avec le framework. Le cadre doit être explicitement lié à la phase de création du lien avec les cadres. Vous voudrez peut-être ouvrir une propre question pour votre problème de liaison, répondre dans les commentaires est fastidieux et vous ne pouvez pas non plus fournir d'informations telles que la sortie du journal de construction.
Mecki
24

Ce problème a été résolu dans LLVM . Le correctif fait partie de LLVM 2.9 La première version de Xcode à contenir le correctif est Xcode 4.2 livré avec LLVM 3.0. L'utilisation de -all_loadou -force_loadn'est plus nécessaire lorsque vous travaillez avec XCode 4.2 -ObjC est toujours nécessaire.

tonklon
la source
Es-tu sûr de ça? Je travaille sur un projet iOS utilisant Xcode 4.3.2, en compilant avec LLVM 3.1 et c'était toujours un problème pour moi.
Ashley Mills
Ok, c'était un peu imprécis. Le -ObjCdrapeau est toujours nécessaire et le sera toujours. La solution de contournement était l'utilisation de -all_loadou -force_load. Et ce n'est plus nécessaire. J'ai fixé ma réponse ci-dessus.
tonklon
Y a-t-il un inconvénient à inclure l'indicateur -all_load (même si ce n'est pas nécessaire)? Cela affecte-t-il le temps de compilation / lancement d'une manière ou d'une autre?
ZS
Je travaille avec Xcode Version 4.5 (4G182) et l'indicateur -ObjC déplace mon erreur de sélecteur non reconnue de la dépendance tierce que j'essaie d'utiliser dans ce qui ressemble aux profondeurs de l'exécution d'Objective C: "- [__ NSArrayM map :]: sélecteur non reconnu envoyé à l'instance ... ". Des indices?
Robert Atkins
16

Voici ce que vous devez faire pour résoudre complètement ce problème lors de la compilation de votre bibliothèque statique:

Accédez aux paramètres de construction Xcode et définissez Effectuer la liaison préliminaire d'un seul objet sur OUI ou GENERATE_MASTER_OBJECT_FILE = YESdans votre fichier de configuration de construction.

Par défaut, l'éditeur de liens génère un fichier .o pour chaque fichier .m. Les catégories obtiennent donc différents fichiers .o. Lorsque l'éditeur de liens examine les fichiers .o d'une bibliothèque statique, il ne crée pas d'index de tous les symboles par classe (Runtime le fera, peu importe quoi).

Cette directive demandera à l'éditeur de liens de regrouper tous les objets dans un seul gros fichier .o et de ce fait, il force l'éditeur de liens qui traite la bibliothèque statique à obtenir l'index de toutes les catégories de classe.

J'espère que cela clarifie cela.

Amosel
la source
Cela a résolu le problème pour moi sans avoir à ajouter -ObjC à la cible de liaison.
Matthew Crenshaw
Après la mise à jour vers la dernière version de la bibliothèque BlocksKit , j'ai dû utiliser ce paramètre pour résoudre le problème (j'utilisais déjà le drapeau -ObjC mais je voyais toujours le problème).
rakmoh
1
En fait, votre réponse n'est pas tout à fait juste. Je ne "demande pas à l'éditeur de liens de regrouper toutes les catégories de la même classe dans un seul fichier .o", il demande à l'éditeur de liens de lier tous les fichiers objets (.o) dans un seul gros fichier objet avant de créer une bibliothèque statique à partir de eux / il. Une fois qu'un symbole est référencé dans la bibliothèque, tous les symboles sont chargés. Cependant, cela ne fonctionnera pas si aucun symbole n'est référencé (par exemple, si cela ne fonctionnera pas s'il n'y a que des catégories dans la bibliothèque).
Mecki
Je ne pense pas que cela fonctionnera si vous ajoutez des catégories à des classes existantes, telles que NSData.
Bob Whiteman
J'ai également du mal à ajouter des catégories aux classes existantes. Mon plugin ne peut pas les reconnaître au moment de l'exécution.
David Dunham
9

Un facteur qui est rarement mentionné chaque fois que la discussion sur les liens de la bibliothèque statique survient est le fait que vous devez également inclure les catégories elles-mêmes dans les phases de construction -> copier les fichiers et compiler les sources de la bibliothèque statique elle-même .

Apple n'insiste pas non plus sur ce fait dans leur publication récente intitulée Using Static Libraries in iOS .

J'ai passé une journée entière à essayer toutes sortes de variantes de -objC et -all_load etc. mais rien n'en est ressorti .. cette question a attiré mon attention sur ce problème. (ne vous méprenez pas ... vous devez encore faire les choses -objC ... mais c'est plus que ça).

aussi une autre action qui m'a toujours aidé est que je construis toujours la bibliothèque statique incluse d'abord seule .. puis je construis l'application englobante ..

abbood
la source
-1

Vous devez probablement avoir la catégorie dans l'en-tête "public" de votre bibliothèque statique: #import "MyStaticLib.h"

christo16
la source