静态库和动态库分别都有两种形式:
在Xcode6之前我们只能在App中使用‘静态库’,如果使用到了‘动态库’那么App是无法上传AppStore的。但Xcode6开始Apple就开放了‘动态库’的使用。
静态库与动态库的区别:
静态库:在项目中使用到静态库,进行编译时静态库会与我们项目本身的‘代码’链接到一起生成目标文件,这样就会导致编译后的目标文件比较大。但因为都链接到一起了所以使用到静态库中的函数时,不需要而外在加载其他函数库。
动态库:在编译时并不会与项目中的‘代码’链接到一起,这样编译后的目标文件就比较小,但在使用到动态库中的函数时,需要提前先加载函数库。
静态库的作用:
当你想将开发当控件分享给别人使用时但又不想暴露具体的实现细节时,可以制作成静态库分享给别人使用。
.a静态库的制作:
1、打开Xcode选择 File/New/Project/iOS/Framework & Library/Cocoa Touch Static Library 创建静态库工程,Product Name命名为AStaticLib
2、添加自己的源码文件到项目中,并将创建项目时Xcode生存的AStaticLib.m文件删除(因为我们不想在这个文件中编写具体的实现代码)
3、在AStaticLib.h文件中import我们所有需要提供给外部使用到的头文件,只在我们内部使用到的类不需要添加。这样做的好处是当别人使用到我们的库时只需要import我们的AStaticLib.h文件即可,这个文件一般与我们库名相同,并称为主头文件。因为我这里只有一个头文件需要对外提供所以只添加一个。
3、需要对外提供的.h头文件还需要添加到Build Phases/Headers中的Public下(如果没有看到Headers点击加号图标添加New Headers Phase),并将我们源码文件中的所有.m文件添加到Build Phases/Compile Sources下(我们需要将我们的源码添加到这里编译),如果这个选项下没有一个.m文件那么在最后进行Build时是不会生成静态库的。
可以将Build Settings/Public Headers Folder Path设置为include/$PROJECT_NAME,这是设置在我们Build时对外提供的.h头文件存放的路径。
4、最后Command+B编译即可,编译后如果没有出现错误,那么.a静态库就已经生成了,并且project navigator项目目录下Products里的libAStaticLib.a文件名也从红色变为黑色。右键Show in Finder打开它,就会看到生成的.a静态库与需要对外提供的头文件,将.a与其他.h头文件导入到其它工程中就可以使用了。
.framework静态库、动态库的制作:
framework库里可以存放很多其它的资源,包括需要对外提供的.h头文件。
1、Xcode6以后提供framework库的模版方便我们制作,在这之前制作framework库是比较麻烦的,需要做很多设置或自己添加模版。同样打开Xcode选择 File/New/Project/iOS/Framework & Library/Cocoa Touch Framework 创建framework库工程,Product Name命名为FrameworkStaticLib
2、看到这里Xcode也只帮我们生成了一个FrameworkStaticLib.h头文件,而且创建framework库默认是动态库Dynamic Library,创建静态库或动态库只需修改这里即可其他设置一样,我们这里将他修改为静态库Static Library。
3、紧接着和上面一样将源码文件添加到项目中,并在FrameworkStaticLib.h文件中import我们所有需要提供给外部使用到的头文件,这里import有点不同因为当我们在其他项目中使用到framework库时import头文件时是已#import <> 的方式所以这里我们使用#import <>方式添加自己的头文件。
4、一样将头文件添加到Build Phases/Headers中的Public下,将我们源码文件中的所有.m文件添加到Build Phases/Compile Sources下。最后Command+B编译即可,和上面一样在project navigator项目目录下Products里右键Show in Finder打开它,就看到我们生成的.framework静态库了。一样将FrameworkStaticLib.framework添加到项目工程里就可以使用了。
到这里我们的.a .framework文件都已经生成了。但是它们都只支持在真机DEBUG模式下使用,因为我是已Scheme/Build Configuration=Debug、iOS Device编译的。我们修改为模拟器在重新编译一下(这里我编译里两次,一次是以真机编译一次是模拟器编译)。编译完成后在~/Library/Developer/Xcode/DerivedData/FrameworkStaticLib-不确定示/Build/Products目录下就有了两个子目录Debug-iphoneos里存放真机使用的静态库,Debug-iphonesimulator存放的是模拟器使用的静态库。
我们可以分别cd到这两个目录里的FrameworkStaticLib.framework目录下通过 xcrun lipo -info FrameworkStaticLib查看支持的CPU结构。
lipo -create Debug-iphoneos/libAStaticLib.a Debug-iphonesimulator/libAStaticLib.a -output libAStaticLib.a
lipo -create Debug-iphoneos/FrameworkStaticLib.framework/FrameworkStaticLib Debug-iphonesimulator/FrameworkStaticLib.framework/FrameworkStaticLib -output FrameworkStaticLib
.a和.framework静态库的使用:
1、.a和.framework静态库的使用基本一致,将生成的库文件添加到项目工程中,并将静态库添加到Build Phases/Link Binary With Libraries中即可使用。这里我新建一个新名为FrameworkStaticLibTest的Single View Application工程,并使用刚刚生成的.framework静态库。
2、因为我静态库里的是一个继承UIView的自定义控件,我在storyboard里的控件中直接使用它,并联线到ViewController中,这时需要import这个控件的头文件,它在静态库中我们 #import
3、这时报了一个错误Unknown class HBRollLabel in Interface Builder file. 因为它找不到HBRollLabel类。在xib设置控件属性的Custom Class/Class属性中设置为静态库中的类时,或静态库中有分类时也会报错,我们需要在target/Build Settings/Other Linker Flags属性中设置‘-ObjC 或 -all_load’即可解决。
正常运行起来了。
另外一种使用方式:
我们可以直接将静态库工程的.xcodeproj拖放到我们项目工程中去,并将静态库添加到Build Phases/Link Binary With Libraries中即可使用,这样的好处是我们可以在不切换窗口到情况下管理项目与编辑修改静态库,项目编译时Xcode会先检测依赖关系并编译他们。开发复杂项目时我们也可以这样划分项目不同模块。
或者新建一个workspace然后将项目工程与静态库工程都添加到workspace里,在将静态库添加到项目工程的Link Binary With Libraries编译即可。