“non reconnu sélecteur envoyé à la classe” lors de l'appel de la catégorie de la méthode à partir d'une bibliothèque

Problème

Cette question peut sembler un peu long, mais j'essaie de donner autant d'informations que possible, car je suis vraiment sidérée par cette.

Je suis actuellement en train de travailler un un bibliothèque qui devrait automatiser document XML de l'analyse. Mais je suis confronté à un problème maintenant les tests de la bibliothèque pour la première fois.

J'ai une bibliothèque de classe appelé CSXDocumentLayout qui représente la mise en page d'un document. Cette classe contient la méthode privée - (NSError *)readLayoutDocument:(NSString *)fpath appelée à partir d'une méthode init.

/* MARK: Reading in Layouts */
- (NSError *)readLayoutDocument:(NSString *)fpath {
    CSXDocumentLayout *layout;
    CSXXMLParser *parser;
    BOOL state;

    layout = [CSXDocumentLayout layoutDocumentLayout];

    parser = [[CSXXMLParser alloc] initWithDocumentLayouts:
              [NSArray arrayWithObject:layout]];
    parser.file = fpath;

    state = [parser parse];

    if(state == NO || parser.error != nil) {
        return parser.error;
    }
    return nil;
}

Cette méthode va lire dans un document XML représentant la page d'un autre document XML. Elle est analysée par la classe CSXXMLParser, je veux tester.

- Je créer un objet représentant une mise en page de document avec +[CSXDocumentLayout layoutDocumentLayout]. Cette méthode est implémentée dans la catégorie CSXDocumentLayout (CSXLayoutObject).

Ci-dessous mon fichier de test:

#import <Foundation/Foundation.h>
#import <CeasyXML.h>

int main(int argc, const char **argv) {
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    NSString *file;

    file = [NSString stringWithUTF8String:__FILE__];
    file = [file stringByDeletingLastPathComponent];
    file = [file stringByAppendingPathComponent:@"Layout.xml"];

    CSXDocumentLayout *layout;
    NSError *error;

    layout = [[CSXDocumentLayout alloc] initWithLayoutDocument:file 
                                                         error:&error];
    if(layout == nil) {
        NSLog(@"Could not create layout: %@", error);
        exit(0);
    }

    NSLog(@"Layout:\n%@", layout);

    [pool release];
    return 0;
}

Ce fichier est compilé en un exécutable séparé lié à ma bibliothèque statique libceasyxml.un. Tout se compile très bien sans aucun avertissement.

Mais quand je le lance j'obtiens un non reconnu sélecteur envoyé à la classe exception:

2012-05-02 16:59:47.620 TestApp[1887:a0f] +[CSXDocumentLayout layoutDocumentLayout]: unrecognized selector sent to class 0x1000064c8
2012-05-02 16:59:47.791 TestApp[1887:a0f] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[CSXDocumentLayout layoutDocumentLayout]: unrecognized selector sent to class 0x1000064c8'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00007fff83e47784 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x00007fff84604f03 objc_exception_throw + 45
    2   CoreFoundation                      0x00007fff83ea11a0 __CFFullMethodName + 0
    3   CoreFoundation                      0x00007fff83e198ef ___forwarding___ + 751
    4   CoreFoundation                      0x00007fff83e15a38 _CF_forwarding_prep_0 + 232
    5   TestApp                             0x0000000100001512 -[CSXDocumentLayout(Private) readLayoutDocument:] + 49
    6   TestApp                             0x00000001000010d4 -[CSXDocumentLayout initWithLayoutDocument:error:] + 96
    7   TestApp                             0x0000000100001017 main + 179
    8   TestApp                             0x0000000100000f5c start + 52
    9   ???                                 0x0000000000000001 0x0 + 1
)

Je trouve très inquiétant que je ne peux pas appeler la méthode de la classe +[CSXDocumentLayout(CSXLayoutObject) layoutDocumentLayout], si je peux appeler à la fois -[CSXDocumentLayout initWithLayoutDocument:error:], et -[CSXDocumentLayout(Private) readLayoutDocument:].

Recherche

J'ai vérifié si la méthode est définie dans les fichiers de sortie en cours d'exécution nm file, et elle est bien partie:

Dans libceasyxml.un, il est défini (nm libceasyxml.a)

...
libceasyxml.a(CSXDocumentLayout+CSXLayoutObject.o):
0000000000000100 t +[CSXDocumentLayout(CSXLayoutObject) classAttributeLayout]
00000000000020e0 s +[CSXDocumentLayout(CSXLayoutObject) classAttributeLayout].eh
000000000000056b t +[CSXDocumentLayout(CSXLayoutObject) documentElementLayout]
0000000000002180 s +[CSXDocumentLayout(CSXLayoutObject) documentElementLayout].eh
0000000000000402 t +[CSXDocumentLayout(CSXLayoutObject) layoutDocumentLayout]
0000000000002148 s +[CSXDocumentLayout(CSXLayoutObject) layoutDocumentLayout].eh
0000000000000200 t +[CSXDocumentLayout(CSXLayoutObject) layoutElementLayout]
0000000000002110 s +[CSXDocumentLayout(CSXLayoutObject) layoutElementLayout].eh
0000000000000000 t +[CSXDocumentLayout(CSXLayoutObject) nameAttributeLayout]
00000000000020b0 s +[CSXDocumentLayout(CSXLayoutObject) nameAttributeLayout].eh
0000000000002098 s EH_frame1
0000000000001c49 s LC0
...

Dans TestApp, il n'est PAS défini (nm TestApp), en fait je ne trouve pas de méthode avec le nom de la catégorie CSXLayoutObject.

...
0000000100001271 t -[CSXDocumentLayout setDocumentClassString:]
00000001000013a8 t -[CSXDocumentLayout setElements:]
0000000100001490 t -[CSXDocumentLayout setName:]
00000001000014db t -[CSXDocumentLayout(Private) readLayoutDocument:]
0000000100004060 t -[CSXElementList dealloc]
00000001000040b0 t -[CSXElementList elements]
...

OriginalL'auteur v1Axvw | 2012-05-02