制作 .framework 静态库的步骤:
1、将需要打包成 Framework 的模块导入到项目中,设置最低支持的 iOS 版本,编译项目保证不报错。4、把 Podfile 中所有库注释掉然后 pod install,然后删除 Podfile 文件同级别目录下其它所有 pods 相关的文件。
8、最后编译即可生成静态库。
打包framework注意事项:
如果有storyboard、xib,需要在对应的视图控制器中添加以下代码:
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"你的静态库名称" withExtension:@"framework"]];
if (bundle) {
// 如果是storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"你的storyboard名称(例如Main)" bundle:bundle];
self = [storyboard instantiateViewControllerWithIdentifier:@"你在storyboard中设置的此视图控制器的id"];
return self;
// 如果是xib
self = [super initWithNibName:@"当前控制器的名称" bundle:bundle];
return self;
}
return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
}
如果需要加载图片:
NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"Frameworks" withExtension:@"framework"]];
NSString *bundlePath = [bundle resourcePath];
UIImage *img = [UIImage imageWithContentsOfFile:[bundlePath stringByAppendingString:@"/aaa.png"]];
使用图片宏:
#define Bundle_With_Framework(name) [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:name withExtension:@"framework"]]
#define Framework_Bundle Bundle_With_Framework(@"Frameworks")
#define ImageNamed(name) Framework_Bundle ? [UIImage imageWithContentsOfFile:[[Framework_Bundle resourcePath] stringByAppendingString:[NSString stringWithFormat:@"/%@", name]]] : [UIImage imageNamed:name]
self.img.image = ImageNamed(@"gg.jpg");
定义一个资源管理宏:
#define Debug_Env 0 // 开发环境
#define Release_Env 1 // 打包环境
#if Release_Env
#define MR_Bundle [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"StaticLibrary" withExtension:@"framework"]]
#define MR_BundleWith(res) [[MR_Bundle resourcePath] stringByAppendingPathComponent:res]
#else
#define MR_Bundle [NSBundle mainBundle]
#define MR_BundleWith(res) res
#endif
这个资源管理宏也可以写得更方便些:
#define Framework_Bundle [[NSBundle mainBundle] URLForResource:@"MRFramework" withExtension:@"framework"]
#define MR_Bundle Framework_Bundle ? [NSBundle bundleWithURL:Framework_Bundle] : [NSBundle mainBundle]
#define MR_BundleWith(res) Framework_Bundle ? [[[NSBundle bundleWithURL:Framework_Bundle] resourcePath] stringByAppendingPathComponent:res] : res
加载图片时:[UIImage imageNamed:MR_BundleWith(@"picture.png")]
加载 storyboard 时:[UIStoryboard storyboardWithName:@"Storyboard" bundle:MR_Bundle];
如果静态库中有 ClassA.h、ClassB.h、ClassC.h 三个头文件,如果只对外暴露 ClassA.h,那么 ClassA.h 中就不能引用 ClassB 和 ClassC,只能在 ClassA.m 中引用。
合并最终的静态库:
模拟器 iPhone5s 以下是 i386 架构,iPhone5s 及以上是 x86_64 架构。
真机iPhone5s 以下是 armv7 架构,iPhone5s 及以上是 arm64 架构。
终端 cd 到生成的 framework 文件夹中,使用命令 lipo -info framework名
,可以看到打出的库是 x86_64 架构的。
如果想同时支持 i386 和 x86_64,设置:
Build Settings —> Architectures —> Build Active Architecture Only —> NO。
模拟器选择真机,编译之后会生成真机的 framework ,架构是 armv7 和 arm64。
以上真机和模拟器的 framework都是 DEBUG 模式下的,打开 Scheme,选为 Release 模式再编译两次(真机和模拟器):
使用命令:lipo -create path1 path2 -output 合成文件名
可以将真机和模拟器两个 framework 合成为一个。其中 path1 和 path2 都是下图中红圈中的文件:
注意,一般是 debug 真机跟 debug 模拟器合成,release 真机跟 release模拟器合成,debug 和 release 不要混合,当然,两个模拟器或者两个真机合成会失败。最终会分别有一个 debug 下和 release 下的 framework。
framework静态库使用步骤:
1、将静态库拖入工程,然后在 Build Phases —> Copy Bundle Resources 中添加该静态库。
2、如果静态库中有分类(Category),则需要在 Build Settings —> Other Linker Flags 中添加 -ObjC 或 -all_load,如果静态库调用 pods 中的第三方库崩溃,则添加$(inherited)。(-ObjC链接所有OC文件,-all_load是链接所有文件,-force_load文件路径是链接指定路径文件,多个静态库文件冲突时使用-force_load,$(inherited)的含义)
3、如果静态库中引用了AFNetworking等第三方库,需要工程也导入这这些库,否则会报头文件找不到的错误。
4、如果使用者导入静态库头文件报警告 missing submodule ,说明静态库中有头文件找不到。如果打包工程名和某个类的名称相同,也会报这个警告,只需要把这个类名改成其它名称即可。
参考《iOS静态库》、《打包Framework并引用CocoaPods管理》。
一般打包了静态库之后,还需要制作说明文档,文档制作可参考《安装和使用AppleDoc》和《使用AppleDoc自动生成项目文档》。