`

创建含有category的静态库,selector not recognized的解决方案[转]

 
阅读更多

http://www.dreamingwish.com/dream-2012/the-create-the-static-the-library-containing-the-category.html

 

一、异常的原因

在连接一个含有category的静态库的时候,往往会得到一个运行时exception “selector not recognized”。

这是由于 UNIX的静态库实现、linker和Objective-C的动态结构三者之间的问题引起的。

Objective-C并不为每个函数定义linker symbol,它只为每个class生成linker symbol。(objc的动态结构)

如果你为一个已存在的class创建了category,那么linker并不知道要将原始class实现和category实现联系起来。这就导致了最终程序中的对象没法响应category中的方法。

要解决这个问题,只要在build静态库时,加上linker flag “-ObjC”即可(在64位osx上和iOS程序上,这样做还不够),这个flag告诉linker将每个定义了class或者category的对象文件都载入静态库。

二、iOS程序还需要做的

用xcode4.3创建lib时,-ObjC这个flag默认是有的(之前的版本不记得了,好像4.x版本的都会默认带这个参数),但是最终程序还是会抛这个异常,这是因为linker的bug,对于64位osx程序和iOS程序,这个bug导致只包含category而不包含class的文件没法从静态库中加载。

所以,apple建议我们为要最终程序的linker加上-all_load或者-force_load参数。

-all_load选项强制linker加载所有包中的所有对象文件,即使文件中没有Objective-C代码也加载。-force_load是从Xcode3.2开始有的,它使得linker获取包加载的控制权,每个-force_load参数后面都必须跟上一个包的路径,然后这个包的所有对象文件都会被加载。

懒人使用-all_load,勤快人使用-force_load。。。

但是这样始终不好,因为这两个选项都可能导致不必要的代码被加载。

三、更好的方法

Three20库给出了一个宏:

#define TT_FIX_CATEGORY_BUG(name) @interface TT_FIX_CATEGORY_BUG_##name @end \
                                  @implementation TT_FIX_CATEGORY_BUG_##name @end

为每个只包含category的文件的category实现前面加上这样一个宏(定义一个空的class),此时不再需要-all_load或者-force_load,因为不存在只包含category的文件。linker的bug也就无从体现。

四、完美的解决方案

就是apple自己想办法解决。。。。

老乔去了,库克请发力。。。

分享到:
评论
2 楼 w11h22j33 2012-05-08  
最近正在写一些库,并且用上篇文章的方式实现了一个头文件对应多个实现文件的一个类。

但是在测试自己的库的时候,发现了这样一个问题:

我有一个类,叫MyClass,并且头文件MyClass.h中声明了基础的一些方法,并且声明一些Category方法,其中包含方法

- (void)getSomeData;

并且该方法在MyClass+Extension.m中实现(其他基础的方法在MyClass.m中实现)。

但是,在测试过程中使用该库,并调用

[MyClass getSomeData]

程序崩溃了,查看崩溃的原因是:unrecognized selector [MyClass getSomeData]
可是编译的时候一点警告都没有。从Objective-C的语法上来讲,这样子完全是没有错的。那么到底是什么原因导致崩溃的呢?
后来在搜索到苹果的这个网页后,才知道要使用静态库中,同一个头文件对应多个实现文件的静态库时,编译时需要加上链接-ObjC才可以正常执行。
加上ObjC后,编译的时候,编译器会将库中所有涉及到某个类的内容全部加载进来,这样会导致生成体积会变大,不过这是理所当然的,因为链入的代码变多了。

所以,最好在分Category去实现的时候,对应的Category还是要有对应的头文件,将不同的Category拆成不同的头文件,只引用有用的头文件,例如把上篇文章的头文件拆成MyClass.h和MyClass+Extension.h,分别对应MyClass.m和MyClass+Extension.m。这样子使用的时候我只要引用MyClass.h和MyClass+Extension.h就可以了,即可以保持Category的好处,又不用引入ObjC使链接器将我不想用的MyClass+ExtensionAnother之类的也链进来导致编译体积变大了。
1 楼 w11h22j33 2012-05-08  
在前面的文章中,我有稍微提了一下iPhone开发中在静态库中使用Category的使用注意。Category本身的使用并没有什么其他要注意的地方,为什么要再提起呢?

在开发3.0的iPhone静态库的时候,遇到了一些问题。尽管我在应用程序链接的选项里头使用-ObjC的选项,我的程序在iPhone上运行时还是Crash了,而且经过定位之后发现,还是由库中的Category相关方法没有被链入导致的;而程序在模拟器上运行却是一点问题没有,Category的相关方法都能正确得到执行。

那么到底是什么原因导致在真机上应用程序没有将Category方法链入呢?答案还是在上次提到的这个苹果官方网页。该网页下方的IMPORTANT里头提到,在64位及iPhone OS系统里,由于编译器的Bug导致了-ObjC选项无法正常将静态库中的类的Category的方法载入!也就是说,假设你的类叫MyClass,并且另外有个Category叫MyClass(Extent),那么如果你的应用程序链接你的库,使用MyClass(Extent)中的方法,程序将会Crash!要提的是,如果你的MyClass(Extent) 的实现是和MyClass的实现是在同一个实现体中,那么该Category的方法还是可以正常使用的,因为编译的时候会一起被载入。

相关推荐

    Selector Not Found(解决方案).md

    Selector Not Found(解决方案).md

    Invalid Selector Function(解决方案).md

    Invalid Selector Function(解决方案).md

    iOS静态库制作实例

    本实例主要探讨如何制作包含Category的iOS静态库,解决静态库中对Category的使用问题。 首先,让我们了解Category在Objective-C中的作用。Category是Objective-C的一个强大特性,允许我们扩展已有类的功能,而无需...

    marvell_Product Selector Guide.pdf

    Marvell Product Selector Guide 是一份详细的产品选择指南,涵盖了 Marvell 公司在以太网(Ethernet)领域的各种解决方案。本指南旨在帮助用户快速选择合适的 Marvell 产品,以满足不同的应用需求。 Ethernet ...

    postcss-selector-not:PostCSS插件进行转换

    postcss-selector-not PostCSS插件,将:not() W3C CSS 4级伪类转换为:not()CSS 3级选择器 安装 $ npm install postcss postcss-selector-not 用法 使用此input.css : p : not ( : first-child , . special ) {...

    前端开源库-has-id-selector

    `has-id-selector`是一个专门针对这一需求的开源库,它允许开发者检查CSS选择器字符串是否包含特定的ID。这个库对于优化代码和确保选择器的有效性具有显著价值。下面我们将详细探讨这个库的功能、使用方法以及在实际...

    前端开源库-matches-selector

    总之,`matches-selector`是一个小巧而强大的前端库,它解决了跨浏览器的元素选择器匹配问题,并通过详尽的单元测试保证了其可靠性。在进行前端开发时,尤其是在需要对元素进行复杂选择器匹配的情况下,`matches-...

    JavaNIO库Selector机制解析.docx

    JavaNIO库Selector机制解析.docx

    android selector注入器

    `android selector注入器` 库的目标就是自动化这个过程,它能够自动为你的View生成相应的Selector,并根据View的状态动态应用这些样式。这样,开发者就可以避免编写大量的XML资源文件,减少重复工作,更专注于业务...

    Selector一个用于替换jQuery的微型JavaScript库

    Selector正是基于这一理念诞生的,它提供了一个轻量级的解决方案,满足了开发者对快速、高效的需求,整个库大小仅为5KB,这对于优化页面加载速度和减少网络带宽消耗具有显著优势。 Selector库的核心功能主要包括...

    Android设置button背景selector和字体selector

    在布局文件中,我们将上述创建的Selector分别设置给Button的`android:background`和`android:textColor`属性。例如: ```xml android:id="@+id/my_button" android:layout_width="wrap_content" android:...

    前端开源库-css-selector-extract

    css-selector-extract 库就是为了解决这个问题而诞生的,它提供了自动化的方式来提取和分析CSS选择器。 这个库的工作原理可能包括以下步骤: 1. **解析CSS**:首先,css-selector-extract会解析输入的CSS代码,将...

    Android selector 完整demo

    在Android开发中,Selector是一种非常重要的资源类型,它主要用于定义视图在不同状态下的外观,如按下、聚焦、默认和选中等。本教程将深入探讨Android中的Selector及其使用方法,通过一个完整的Demo来帮助你理解和...

    java selector 测试并发

    `.classpath`、`MANIFEST.MF`、`.project`、`.settings`、`.metadata`和`bin`都是与Java开发环境相关的文件,它们可能包含项目配置、依赖库信息、源代码目录结构等,但不是直接涉及Java Selector并发测试的代码。...

    带圆角的selector

    6. **代码动态设置**:除了在XML中静态设置,我们也可以在Java或Kotlin代码中动态地为视图设置`Selector`,例如使用`button.setBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.your_selector))`。...

    flutter file-selector

    Flutter的file_selector插件可以帮助开发者在移动应用中方便地选择文件。 要使用file_selector插件,首先需要将插件的依赖项添加到pubspec.yaml文件中,并运行flutter pub get命令获取插件的最新版本。 在插件使用...

    Python库 | appium_selector-1.0.1.tar.gz

    `appium_selector-1.0.1.tar.gz` 是一个针对Python编程语言的库,用于自动化测试移动应用程序。这个压缩包包含的是 `appium_selector` 库的版本1.0.1。`appium_selector` 是一个辅助工具,它与Appium集成,帮助...

    Contact Selector控件的使用

    《Contact Selector控件在InfoPath中的应用》 在InfoPath设计复杂的表单时,Contact Selector控件是一个不可或缺的工具,它允许用户从SharePoint的人力资源列表或Outlook联系人中选择并插入联系人信息。这个功能...

    Selector

    标题中的"Selector"一词在IT领域通常指的是选择器,它是编程语言或样式表中用于选取元素的关键概念。在Web开发中,特别是CSS(层叠样式表)中,选择器用于定位HTML或XML文档中的特定元素,以便应用样式。同时,选择...

    iconFont 实现selector的Demo

    1. **创建selector文件**:在res/drawable目录下创建一个XML文件,如`icon_selector.xml`,并定义不同状态下的图标样式。 2. **定义状态**:在selector文件中,使用`<item>`标签定义图标在不同状态(如`android:...

Global site tag (gtag.js) - Google Analytics