如果你想偷懒,务必要学会静态库的制作,一定要有自己的一套静态库。优点:易维护、整洁性、封装。
一、静态库和动态库的区别
1.静态库(.a和.framework) 动态库(.liby和.framework)
2.平时我们所使用的第三方SDK都是静态库,而iOS系统库都是动态库
3.静态库在项目编译时完整的拷贝到可执行文件中,被多次使用就有多份冗余拷贝,而动态库是系统运行时由系统动态加载到内存中,系统只加载一次,多个程序共用,减少内存。
4.静态库很大的一个优点就是减少耦合性,因为静态库中不可以包含其他静态库,使用的时候再导入依赖库,最大限度保证每一个静态库的独立性,不会重复引用。动态库在制作的时候可以包含静态库,也能自动link所需的依赖库。
注:苹果禁止在iOS开发中使用动态库
二、制作出的Debug静态库和Release静态库的区别
1.Debug含有完整的符号信息,方便调试。Release不包含完整的符号信息。
2.Debug不会对代码进行优化。Release对代码进行了优化。
3.Debug版静态库比Release版静态库小。
4.Debug执行速度慢。Release速度稍快。
三、.a 静态库的制作
1.新建静态库工程:Create a New Xcode project -> 选择Cocoa Touch Static Library
2.配置最低版本支持:Target -> Deployment Target
3.设置适配所有模拟器:Target -> Build Setting -> Build Active Architecture Only将其改为NO
4.写入自己封装的文件
5.设置.h文件为公开文件:Target -> Build Phases -> 左上角+号 -> 新建Header Phase -> 添加.h文件 -> 最后将Project中的.h文件拖拽到Public下
6.生成4种.a静态库文件:真机Debug、真机Release、模拟器Debug、模拟器Release,编译运行就可以生成,最后可以在Products下的.a中show in finder中可以看到。
7.合并Debug两个包和Release两个包:lipo -create 静态库A路径 静态库B路径 -output 新静态库路径及自定义的名称
8.静态库的使用:新建工程,引入静态库和.h文件使用即可
遇到的坑:
(1)无法合并静态库:lipo -create 静态库A路径 静态库B路径 -output 新静态库路径及自定义的名称(参考文章:无法合并静态库)
(2)类别在静态库中无法使用导致崩溃:Target -> Build Setting -> Linking -> 修改Other Linker Flags -> -all_load或_force_load
四、.framework 静态库的制作
1.新建静态库工程:Create a New Xcode project -> 选择Cocoa Touch Framework
2.配置最低版本支持:Target -> Deployment Target
3.设置适配所有模拟器:Target -> Build Setting -> Build Active Architecture Only将其改为NO,继续搜索mach -> 修改mach -O -Type -> static Library
4.写入自己封装的文件
5.引入其他第三方库,如果有其他第三方库的话,切记导入第三方静态库的时候不要Add to targets
6.设置.h文件为公开文件:Target -> Build Phases -> Header -> 将Project中的.h文件拖拽到Public下
7.生成4种.a静态库文件:真机Debug、真机Release、模拟器Debug、模拟器Release,编译运行就可以生成,最后可以在Products下的.a中show in finder中可以看到。(Debug合并、Release合并)
8.合并Debug两个包和Release两个包:lipo -create 静态库A路径 静态库B路径 -output 新静态库路径及自定义的名称(合并的是Framework下的白色文件framework文件)
9.替换刚才framework下的那个文件,换成新合并的
10.静态库的使用:新建工程,引入静态库即可使用
遇到的坑:
(1)项目中导入框架出现警告“missing submodule 'framework'”,解决方法就是在创建Framework时候,自带的.h文件中加入这个代码即可 “#import <framework/tool.h>”
(2)资源文件.bundle:静态库中有使用图片、音频等资源文件,可以将其打包成.bundle文件供静态库使用(直接文件夹改后缀名.bundle),使用方法:(.bundle文件无法封装到framework里,需要将.framework,.bundle同时导入项目中才能正常使用)
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"BundleName" ofType:@"bundle"]];
NSString *imageName = [[bundle resourcePath] stringByAppendingPathComponent:assetName];
[_imageView setImage:[UIImage imageWithContentsOfFile:imageName]];
(3)替换完文件后记得改回原来的名字哦!XHKit
五、拓展
ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中
all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数。
force_load:所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载
参考文章:静态库