从iPhone静态库中包含的类别调用方法会导致NSInvalidArgumentException

Cor*_*oyd 33 iphone xcode cocoa-touch exception

我已经创建了一个静态库来存放我的一些代码,比如类别.

我在"UIView-Extensions.h"中有一个名为Extensions的UIViews类别.

在这个类别中我有一个叫做的方法:

- (void)fadeOutWithDelay:(CGFloat)delay duration:(CGFloat)duration;
Run Code Online (Sandbox Code Playgroud)

调用此方法在Debug配置的模拟器上运行正常.

但是,如果尝试在设备上运行应用程序,我会收到NSInvalidArgumentException:

[UIView fadeOutWithDelay:duration:]: unrecognized selector sent to instance 0x1912b0
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIView fadeOutWithDelay:duration:]: unrecognized selector sent to instance 0x1912b0
Run Code Online (Sandbox Code Playgroud)

似乎由于某种原因UIView-Extensions.h没有被包含在设备构建中.


我检查/尝试了什么

我确实尝试为NSString包含另一个类别,并且遇到了同样的问题.

其他文件,如整个类和函数都可以正常工作.这是一个在类别中出现的问题.

我做了一个干净的所有目标,但没有解决问题.

我检查了静态库项目,这些类别包含在目标的"copy headers"和"compile sources"组中.

静态库包含在主项目"链接二进制文件库"组中.

我添加静态库的另一个项目工作得很好.

我删除并重新添加静态库,没有运气

-ObjC链接器标志已设置

有任何想法吗?


nm输出

libFJSCodeDebug.a(UIView-Extensions.o):
000004d4 t -[UIView(Extensions) changeColor:withDelay:duration:]
00000000 t -[UIView(Extensions) fadeInWithDelay:duration:]
000000dc t -[UIView(Extensions) fadeOutWithDelay:duration:]
00000abc t -[UIView(Extensions) firstResponder]
000006b0 t -[UIView(Extensions) hasSubviewOfClass:]
00000870 t -[UIView(Extensions) hasSubviewOfClass:thatContainsPoint:]
000005cc t -[UIView(Extensions) rotate:]
000002d8 t -[UIView(Extensions) shrinkToSize:withDelay:duration:]
000001b8 t -[UIView(Extensions) translateToFrame:delay:duration:]
         U _CGAffineTransformRotate
000004a8 t _CGPointMake
         U _CGRectContainsPoint
         U _NSLog
         U _OBJC_CLASS_$_UIColor
         U _OBJC_CLASS_$_UIView
         U ___CFConstantStringClassReference
         U ___addsf3vfp
         U ___divdf3vfp
         U ___divsf3vfp
         U ___extendsfdf2vfp
         U ___muldf3vfp
         U ___truncdfsf2vfp
         U _objc_enumerationMutation
         U _objc_msgSend
         U _objc_msgSend_stret
         U dyld_stub_binding_helper
Run Code Online (Sandbox Code Playgroud)

Cor*_*oyd 30

唯一有效的解决方案包括:

"-all_load"

在其他链接器标志中.

编辑:确保将此标志添加到项目中,包括静态库,而不是静态库本身.

我知道这不是正确的方法,但它现在正在运作.

它可能是一个OS 3.0问题,因为这也是Three20的解决方案.

  • 只是想补充一点,你需要将这个标志添加到项目中,包括静态库,而不是静态库本身. (7认同)

Jas*_*oco 14

遗憾的是,由于Objective-C运行时的工作类型和动态特性,并非所有类型都适用于静态库.您收到此错误的原因是静态库中的类别实现从未实际链接到可执行映像,因为编译器无法知道在运行时将需要实现代码.

为了解决这个问题,您可以强制链接器从静态存档中复制任何和所有Objective-C类和类别图像的目标文件.缺点是您的可执行文件将包含您可能根本不使用的类的图像代码.要使链接器包含类别代码,请添加-ObjCOTHER_LD_FLAGSXcode中的构建设置.您的类别实现现在将从静态存档复制到您的可执行文件,您将不会获得运行时异常.


小智 6

我刚刚和一位Apple工程师讨论了这个问题,这个版本已经在版本> 100的ld中得到了解决.这包含在XCode4中.他带我走过这个,我自己尝试了,确实类别问题已经解决了.

取出"-all_load"并使用新链接器返回Build Settings中的"-ObjC".


Eri*_*urg 5

如果您使用的是Xcode 3.2,则可以避免使用-all_load,而是仅使用-force_load作为相关库,这应该稍微高效一些.

最近更新的Apple Technical QA中描述了这一点:http://developer.apple.com/mac/library/qa/qa2006/qa1490.html