文件后缀名
h :头文件。头文件包含类,类型,函数和常数的声明。
.m :源代码文件。这是典型的源代码文件扩展名,可以包含Objective-C和C代码。
.mm :源代码文件。带有这种扩展名的源代码文件,除了可以包含Objective-C和C代码以外还可以包含C++代码。仅在你的Objective-C代码中确实需要使用C++类或者特性的时候才用这种扩展名
.cpp:只能编译C++;
注意:.m 和.mm 的区别是告诉gcc 在编译时要加的一些参数。当然.mm还可以命名成.m,但在编译时要手动加参数(麻烦)。
Framework search path:where to search frameworks (.framework bundles) in addition to system frameworks paths. Not used very much in iOS development, officially there is no developer iOS frameworks.
Header search path:where to search for header files (.h files) in addition to system paths. Usually you’ll need it if you are using a 3rd party library. Set it to the directory where you have the header files. If you use a directory to include the header (example: #import “mylibrary/component.h”) set it to the parent directory.
In xcconfig files you use this variable:
HEADER_SEARCH_PATHS = “/path/to/headers/container/directory
Library search path:where to search for library files in addition to system paths. Xcode will set it automatically if you drag a library (.a files) into the project. To set it manually, use the directory where the library is located.
In xcconfig files you use this variable:
LIBRARY_SEARCH_PATHS = “/path/to/libraries/container/directory”
说明:All three can hold a list of paths, with quotes, separated by space.
该设置,用来填写XCode的链接器参数,如:-ObjC -all_load -force_load等。(xcode采用的链接器为ld–GNU,主要用于将obj文件连接成可执行文件。可以通过man ld 命令了解更多)
还记得我们在学习C程序的时候,从C代码到可执行文件经历的步骤是:源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件
在最后一步需要把.o文件和C语言运行库链接起来,这时候需要用到ld命令。源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件。
参数说明:
(在ios开发过程中,有时候会用到第三方的静态库(.a文件),然后导入后发现编译正常但运行时会出现selector not recognized的错误,从而导致app闪退。阅读库文件的说明文档,你可能会在文档中发现诸如在Other Linker Flags中加入-ObjC或者-all_load这样的解决方法,原因?)
报selector not recognized为什么会闪退:
The"selector not recognized"runtime exception occurs duetoan issuebetweentheimplementationofstandard UNIX static libraries,thelinkerandthedynamic natureofObjective-C. Objective-Cdoesnotdefine linker symbolsforeach function (ormethod,inObjective-C) - instead, linker symbols are only generatedforeachclass. If you extend a pre-existingclasswithcategories,thelinkerdoesnotknowtoassociatetheobject codeofthecoreclassimplementationandthecategory implementation. This prevents objects createdintheresultingapplicationfromrespondingtoa selectorthatisdefinedinthecategory.
1
翻译过来,大概意思就是Objective-C的链接器并不会为每个方法建立符号表,而是仅仅为类建立了符号表。这样的话,如果静态库中定义了已存在的一个类的分类,链接器就会以为这个类已经存在,不会把分类和核心类的代码合起来。这样的话,在最后的可执行文件中,就会缺少分类里的代码,这样函数调用就失败了。
-ObjC,一般这个参数足够解决前面提到的问题,苹果官方说明如下:
This flag causesthelinkertoloadeveryobjectfileinthelibrarythatdefines an Objective-Cclassorcategory. While this option will typicallyresultina larger executable (duetoadditional object code loadedintotheapplication),itwill allowthesuccessful creationofeffective Objective-C static librariesthatcontaincategoriesonexisting classes.
1
简单说来,加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中,虽然这样可能会因为加载了很多不必要的文件而导致可执行文件变大,但是这个参数很好地解决了我们所遇到的问题。但是事实真的是这样的吗?
如果-ObjC参数真的这么有效,那么事情就会简单多了。
Important: For64-bitandiPhone OS applications, thereisa linker bugthatprevents -ObjCfromloading objects filesfromstatic librariesthatcontainonly categoriesandno classes. The workaroundistousethe-allloador-forceload flags.
1
当静态库中只有分类而没有类的时候,-ObjC参数就会失效了。这时候,就需要使用-all_load或者-force_load了。
-all_load会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force _load参数。
-force _load所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载。(-force_load后面需要文档路径)