iPhone开发中静态库中的Category使用

http://blog.csdn.net/pjk1129/article/details/7255163

第一种,官方推荐的,但往往不是很好用的。使用-all_load选项,这会导致所有的类的方法都会被载入,不管“你的程序”有没有用到,所有的,包括系统的,方法会被载入。这个方法不仅会导致你的目标程序大小增大,而且往往容易引起一些冲突,而这些冲突往往你无法解决(常常出现在你链接的各种库中)。或者你可以使用-force_load,这个你可以指定要载入所有方法的库,这个算一个还不错的解决方法,但是仅在Xcode3.2之后才支持,如果你必须支持低版本的SDK的话,那么很悲剧,您这两种方法都不大适用!(悲剧如我,就是这种情况)

第二种,你使用的Category是你自己的类的Category,这是个常见的情况,自己的一个类比较大,分拆成多个文件时常用的手段。经过一段时间的思考,发现这种情况的解救方法还是比较容易的,虽然个人认为有点不优雅,但是可以很简单的解决掉。

你可以将你所有的Category的头文件包含到类的主头文件或者主实现文件中,并且直接在你的类的主实现文件中去import你的各个Category的实现文件。这样,编译器在链入你的类的主方法时,你的各个Category实现由于被import到你的类主实现文件中,所以他可以找到你的Category方法,并将该方法链入目标文件。当然,这个方法不太优雅就是了。

第三种,就是你使用的是系统API某个类的Category,比如你为UILabel增加了个Category:UILabel(MyExtent).这个其实也很麻烦,刚开始也试了很多方法,网上的一些方法也试过,但是貌似还是不管用,最后换了个想法想,这个和自己类的Category有什么区别,貌似一样没区别阿。所以最后试了一下,只要找一个必定会使用的类,将Category的头文件和实现文件import到该类的主实现文件中,这样编译器就也能找到这些Category方法了。虽然一样解决了问题,还是那句话,一点都不优雅!

-ObjC 还是要写的 

一、异常的原因

在连接一个含有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库给出了一个宏:

1
2
#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也就无从体现。  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值