8

Problem

Diese Frage stellen kann etwas lang erscheinen, aber ich versuche, so viele Informationen wie möglich zu geben, da ich wirklich von dieser versetzt würde.„Unbekannter Selektor gesendet Klasse“, wenn die Kategorie-Methode aus einer Bibliothek

Ich arbeite derzeit eine library, die XML-Dokumentanalyse automatisieren sollte. Aber ich stoße jetzt auf ein Problem und teste die Bibliothek zum ersten Mal.

Ich habe eine Bibliotheksklasse mit dem Namen CSXDocumentLayout, die das Layout eines Dokuments darstellt. Diese Klasse enthält die private Methode - (NSError *)readLayoutDocument:(NSString *)fpath, die von einer init-Methode aufgerufen wird.

Diese Methode liest ein XML-Dokument ein, das das Layout eines anderen XML-Dokuments darstellt. Es wird von der Klasse CSXXMLParser geparst, die ich testen möchte.

Ich erstelle ein Objekt, das ein Layoutdokument mit +[CSXDocumentLayout layoutDocumentLayout] darstellt. Diese Methode ist in der Kategorie CSXDocumentLayout (CSXLayoutObject) implementiert.

Unten ist meine Testdatei:

#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; 
} 

Diese Datei kompiliert in eine separaten ausführbaren Datei verknüpfen meine statische Bibliothek libceasyxml.a. Alles kompiliert gut ohne Warnungen.

Aber wenn ich es laufen bekomme ich einen Unbekannter Selektor an Klasse Ausnahme gesendet:

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 
) 

ich es sehr störend, dass ich nicht die Klassenmethode +[CSXDocumentLayout(CSXLayoutObject) layoutDocumentLayout] nennen kann, obwohl ich beide -[CSXDocumentLayout initWithLayoutDocument:error:] nennen kann, und -[CSXDocumentLayout(Private) readLayoutDocument:].

Forschung

I geprüft, ob das Verfahren in den Ausgangsdateien definiert wird durch nm file ausgeführt wird und es ist auch zum Teil:

In libceasyxml.a, sie definiert ist (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 
... 

In TestApp, ist es nicht (nm TestApp) definiert, eigentlich kann ich keine Methode mit dem Kategorienamen CSXLayoutObject finden.

... 
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] 
... 

Antwort

26

Ich vermute, Sie sind in ein bekanntes Problem von categories embedded in static libraries geraten.

Wenn ich richtig bin, versuchen Sie, mit den Linker-Flags -ObjC zu kompilieren (und wenn das nicht genug ist, auch -all_load) und Ihr Problem sollte verschwinden.

+0

Arbeitete perfekt, danke. – v1Axvw

+3

Für zukünftige Leser musste ich das Flag zu "anderen Linking Flags" im Menü "Verknüpfung" hinzufügen. (ios 6.1, xcode 4.3) – Kevin

+0

Während diese Antwort oft die Lösung ist, ist die andere, die von Ace zur Verfügung gestellt wird, eine großartige Ergänzung und deckt einen anderen möglichen Fall ab. –

3

Obwohl die Antwort bereits ausgewählt wurde, wünschte ich, die Lösung für mein Problem wäre hier, so einfach es auch sein mag. Stellen Sie sicher, dass Ihre Klasse im Feld Target Membership unter dem Bereich File Inspector ordnungsgemäß überprüft wird.Wenn Sie dies nicht tun, ist es nur natürlich, den Fehler unrecognized selector sent to class zu erhalten.

+0

Das war es für mich! Danke, lieber Fremder! –