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

时间:2009-05-31 21:01:24

标签: iphone cocoa-touch xcode exception

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

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

在这个类别中,我有一个名为:

的方法
- (void)fadeOutWithDelay:(CGFloat)delay duration:(CGFloat)duration;

在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

由于某种原因,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

9 个答案:

答案 0 :(得分:30)

唯一有效的解决方案是:

“ - all_load”

在其他链接器标志中。

编辑:请务必将此标志添加到项目中,包括静态库,而不是静态库本身。

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

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

答案 1 :(得分:14)

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

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

答案 2 :(得分:6)

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

取出“-all_load”并使用新链接器返回Build Settings中的“-ObjC”。

答案 3 :(得分:5)

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

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

答案 4 :(得分:3)

链接类别需要-all_load-force_load个链接器标记的问题是fixed in LLVM。该修补程序作为LLVM 2.9的一部分提供。包含该修复程序的第一个Xcode版本是带有LLVM 3.0的Xcode 4.2。 使用Xcode 4.2时不再需要上述修复。链接ObjC二进制文件时仍需要-ObjC标志

答案 5 :(得分:2)

我最近遇到了这个问题。当我注意到另一个我有DID工作的类别时,我无法让-all_load工作。我对这个类别很懒,并将其包含在另一个文件中。

我最终创建了一个虚拟类(没有方法,实例变量),并在该虚拟类的.m文件中包含了我的类别的实现。执行此操作后,即使我删除了-all_load标志,我的类别也开始工作。

这是在iPhone OS 3.1.3上。

这肯定不是修复它的正确方法,但似乎有效。

我的blog上的完整示例代码适用于我的(普通)类别。

答案 6 :(得分:2)

我刚遇到同样的问题,但添加所描述标志的任意组合(-ObjC,-all_load,-force_load)都不起作用。

事实证明,在将文件添加到项目时,我没有选中“添加到目标”框。我从项目中删除了文件并再次添加它们,这次确保选中了该框。这解决了这个问题。

答案 7 :(得分:0)

在过去,我能够强制将类别与-u .objc_category_name_UIView_Extensions链接,但是3.0 dev环境已经破坏,唯一的选择似乎是-all_load。

答案 8 :(得分:0)

我的静态库中的类别存在同样的问题。在我的情况下,“-all_load”没有帮助,因为它导致了大量的构建错误(我的静态库是另一个私有C / C ++库的包装)。

我通过http://iphonedevelopmentexperiences.blogspot.com/2010/03/categories-in-static-library.html建议的黑客解决了这个问题,只是在类别文件中添加了一个虚拟(空)类定义。使用这个hack,我保留了“-ObjC”但在应用程序链接器设置中删除了“-all_load”,它在设备上运行良好。