Xcode里的-ObjC,-all_laod和-force_load的作用

来源:互联网 发布:西安市汇知中学 编辑:程序博客网 时间:2024/05/21 09:08

前两天公司线上项目突然出现奔溃现象,发了一个报错截图让我看,内容为:
‘unrecognized selector sent to instance 0x7f9029630bc0’,
很奇怪怎么会出现这种境况,想了一会问了一下其他的开发人员,是不是在集成我给的静态库后忘记在Other Linker Flags添加-ObjC或者-all_load,确认没有后重新添加程序正常运行了.
我们在日常开发中,会用到第三方静态库(.a文件)或者自己打包静态库供别人使用,会在Other Linker Flags中添加-ObjC或-all_laod或-force_load下面简单介绍下各种用途:

  • 链接器
    首先先介绍下Other Linker Flags,说白了,就是ld命令除了默认参数外的其他参数.id命令实现的是链接器的工作,详细说明可以在终端man id查看.
    一个程序从简单易读的代码到可执行文件往往要经历以下步骤:
    源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件

    源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件。

  • 闪退原因
    苹果官方Q&A上有这么一段话:
    The “selector not recognized” runtime exception occurs due to an issue between the implementation of standard UNIX static libraries, the linker and the dynamic nature of Objective-C. Objective-C does not define linker symbols for each function (or method, in Objective-C) - instead, linker symbols are only generated for each class. If you extend a pre-existing class with categories, the linker does not know to associate the object code of the core class implementation and the category implementation. This prevents objects created in the resulting application from responding to a selector that is defined in the category.
    翻译过来,大概意思就是Objective-C的链接器并不会为每个方法建立符号表,而是仅仅为类建立符号表.这样,如果静态库中定义了已存在的一个类的分类,链接器就会以为这个类已经存在,不会把分类和核心代码结合起来.这样的话,在最后的可执行文件中,就会缺少分类里的代码,这样函数调用就失败了.

  • 方法分析
    1.-ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中,虽然这样可能会因为加载了很多不必要的文件而导致可执行文件变大,但是这个参数很好地解决了我们所遇到的问题.

    当静态库中只有分类而没有类的时候,-ObjC参数就会失效了。这时候,就需要使用-all_load或者-force_load了.

    2.-all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数.
    3.-force_load所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载.

原创粉丝点击