“发送到类的未识别的选择器”当从库中调用类别方法 [英] "unrecognized selector sent to class" when calling category method from a library
问题描述
问题
这个问题可能看起来有点长,但我尽量提供尽可能多的信息,因为我真的错过了这一点。
我目前正在工作一个库,它应该自动化XML文档解析。
我有一个库类 CSXDocumentLayout
其表示文档的布局。这个类包含从init方法调用的私有方法 - (NSError *)readLayoutDocument:(NSString *)fpath
。
/ * MARK:Reading in Layouts * /
- (NSError *)readLayoutDocument:(NSString *)fpath {
CSXDocumentLayout * layout;
CSXXMLParser * parser;
BOOL状态;
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;
}
此方法将读入表示其他XML文档的布局的XML文档。它由类 CSXXMLParser
解析,我要测试。
我创建一个表示布局文档的对象与 + [CSXDocumentLayout layoutDocumentLayout]
。这个方法在 CSXDocumentLayout(CSXLayoutObject)
类别中实现。
下面是我的测试文件:
#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(@无法创建布局:%@,错误);
exit(0);
}
NSLog(@Layout:\ n%@,layout);
[pool release];
return 0;
}
此文件编译为与我的静态库链接的单独的可执行文件libceasyxml .a 。
但是当我运行它时,我得到一个无法识别的选择器发送到类异常:
2012-05-02 16:59:47.620 TestApp [1887:a0f] + [CSXDocumentLayout layoutDocumentLayout]:无法识别的选择器发送到类0x1000064c8
2012-05-02 16:59:47.791 TestApp [1887:a0f] ***由于未捕获异常NSInvalidArgumentException终止应用程序,原因:'+ [CSXDocumentLayout layoutDocumentLayout]:无法识别的选择器发送到类0x1000064c8'
***首次调用堆栈:
(
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
)
我发现很不安,我不能调用类方法 + [CSXDocumentLayout(CSXLayoutObject)layoutDocumentLayout]
,虽然我可以调用 - [CSXDocumentLayout initWithLayoutDocument:error:]
- [CSXDocumentLayout(Private)readLayoutDocument:]
。
研究
$ b b
我通过运行 nm文件
检查了输出文件中是否定义了该方法,它部分是:
在libceasyxml.a中,定义为(nm libceasyxml.a)
...
libceasyxml.a(CSXDocumentLayout + CSXLayoutObject.o):
0000000000000100 t + [CSXDocumentLayout(CSXLayoutObject)classAttributeLayout]
00000000000020e0 s + [CSXDocumentLayout classAttributeLayout] .eh
000000000000056b t + [CSXDocumentLayout(CSXLayoutObject)documentDelementLayout]
0000000000002180 s + [CSXDocumentLayout(CSXLayoutObject)documentElementLayout] .eh
0000000000000402 t + $ b 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
...
在TestApp中,未定义(nm TestApp)实际上我找不到类别名为
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]
...
解决方案我怀疑您遇到了嵌入在静态库中的类别。
如果我是对的,尝试使用链接器标志
-ObjC
编译(如果这还不够,-all_load
),您的问题应该会消失。Problem
This question may seem a bit long, but I try to give as much information as possible, since I am really staggered by this.
I am currently working an a library which should automate XML document parsing. But I am running into a problem now testing the library for the first time.
I have a library class called
CSXDocumentLayout
which represents the layout of a document. This class contains the private method- (NSError *)readLayoutDocument:(NSString *)fpath
called from an init method./* 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; }
This method will read in an XML document representing the layout of an other XML document. It is parsed by the class
CSXXMLParser
, which I want to test.I create an object representing a layout document with
+[CSXDocumentLayout layoutDocumentLayout]
. This method is implemented in the categoryCSXDocumentLayout (CSXLayoutObject)
.Below is my test file:
#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; }
This file compiles to a separate executable linked to my static library libceasyxml.a. Everything compiles just fine without any warnings.
But when I run it I get a unrecognized selector sent to class 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 )
I find it very disturbing that I cannot call the class method
+[CSXDocumentLayout(CSXLayoutObject) layoutDocumentLayout]
, though I can call both-[CSXDocumentLayout initWithLayoutDocument:error:]
, and-[CSXDocumentLayout(Private) readLayoutDocument:]
.Research
I checked if the method is defined in the output files by running
nm file
and it is, well partly:In libceasyxml.a, it is defined (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, it is NOT defined (nm TestApp), actually I can't find any method with the category name
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] ...
解决方案I suspect you have run into a known problem of categories embedded in static libraries.
If I am right, try to compile with the linker flags
-ObjC
(and if that is not enough, also-all_load
) and your problem should disappear.这篇关于“发送到类的未识别的选择器”当从库中调用类别方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!