ios-sdk静态库framework开发
ios-sdk静态库framework开发
前篇
- iOS-SDK开发经验分享 - https://www.jianshu.com/p/cbb1f54b89d2
- Unity iOS教程之Xcode打包framework在Unity调用 - https://jingyan.baidu.com/article/9080802204bd19fd91c80f3e.html
- 包含 Bundle 资源的 framework 的正确打包方式 - https://www.jianshu.com/p/c92c08d8afda
- xcode6 framework missing submodule xxx 警告 - https://www.cnblogs.com/cocoajin/p/4645446.html
主要是给 unity 开发 ios 插件, 以 framework 的形式集成到 unity 中, 供 unity 调用 ios 原生接口.
头文件引入方式
创建模块 UnityApi 时会一起创建一个头文件 UnityApi.h, 这个头文件里用来 import 改模块里的需要导出的 头文件, 如
UnityApi.h
1
2
3
4#import <UnityApi/UnityPlugin.h>
#import <UnityApi/Tools.h>
#import <UnityApi/Model.h>
#import <UnityApi/Define.h>即使文件存放有目录层级, 但是 import 的时候是没有目录层级, 只有 <模块/头文件>
文件引入
UnityApi 模块内 引入文件内部文件是用到什么就引入什么
UnityApi 模块外 的其他模块, 只需要引入 UnityApi.h 即可
创建 静态 framework
创建 framework, 如: UnityApi
编译设置
点击目标工程 >> 选择你创建的 Framework >> 点击工程设置 >> 做出如下修改
1
2
3
4
5
6
7
8Build Settings >> Dead Code Stripping >> 设置为NO
Build Settings >> Strip Debug Symbol During Copy >> 全部设置为NO
Build Settings >> Strip Style >> 设置为Non-Global Symbols
Build Settings >> Base SDK >> Latest iOS(iOS 选择最新的)
Build Settings >> Link With Standard Libraries >> 设置为 NO
Build Settings >> Mach-O Type >> Static Library
对于Mach-O Type有两种情况:(1)选择 Static Library 打出来的是静态库;(2)选择 Relocatable Object File 打出来是动态库。编写代码 并 导出头文件
外部需要访问的头文件需要导出
在对应的 target 上, 把头文件拖到 public 下
构建 真机/模拟器 的 framework
切到 对应的模块 及 要编译的 真机 (any ios devices) or 模拟器
cmd + b 进行构建
构建成功后在 products 目录下会显示成 白色.
合并 真机 和 模拟器 的 framework. 命令:
lipo -create
(如果只是 真机 或 模拟器 其中一个使用, 就不需要合并了, 直接使用 framework)1
$ lipo -create /Users/wilker/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphoneos/UnityApi.framework/UnityApi /Users/wilker/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphonesimulator/UnityApi.framework/UnityApi -output UnityApi
查看合并后支持的架构
1
2$ lipo -info UnityApi
Architectures in the fat file: UnityApi are: armv7 x86_64 arm64 // x86_64 就是 模拟器 支持的架构, armv7 arm64 都是真机支持的架构附: 移除 cpu 架构
1
2lipo -remove i386 ProjectFramework_SDK -o ProjectFramework_SDK
lipo -remove x86_64 ProjectFramework_SDK -o ProjectFramework_SDK
然后 选择 真机 (或 模拟器 都行) 导出的 framework
- 删除原有的 静态库文件 和
_CodeSignature
目录 - 将合并后的 静态库文件 拖入 framework 中. 然后就可以使用这个 framework.
- 删除原有的 静态库文件 和
bundle 打包资源
直接创建一个文件加, 重命名为 res.bundle.
右键 bundle -> show package contents 可以进入到 bundle 里, 然后就可以往里面拖资源
将 bundle 拖入项目, 会自动引入 bundle 资源
加载. 因为是 引用资源的方式, 最终 bundle 都是拷贝到 app 的根目录下, 所以加载资源时都是使用相对根目录的资源
UnityApi 模块中加载代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17+(void)addImgForView:(UIViewController*) ctrl {
// 方式 1: bundle 内相对路径 (无文件后缀)
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"res" ofType:@"bundle"];
NSBundle *resourceBundle = [NSBundle bundleWithPath:bundlePath];
NSString* picPath = [resourceBundle pathForResource:@"pic01" ofType:@"png"];
// UIImage* img = [UIImage imageWithContentsOfFile:picPath];
// 方式 2: 绝对路径 (有文件后缀)
UIImage *img = [UIImage imageNamed:@"res.bundle/pic01.png"];
UIImageView *imageV = [[UIImageView alloc]init];
imageV.frame = CGRectMake(100, 100, 100, 100);
imageV.backgroundColor = [UIColor greenColor];
imageV.image = img;
[ctrl.view addSubview:imageV];
}
加载 framework 的资源
关于静态库不能使用 bundleForClass 获取路径的问题 - https://stackoverflow.com/questions/42555027/nsbundle-bundlewithidentifier-returning-null-for-static-framework-and-resource-b
解释如下:
1
Static libraries are just compilations of object files (multiple .o files in one .a file). Their identity disappears when they're linked into an executable target (app binary or dynamic library), and they bring no resources other than code and constant data.
bundleForClass 只能是在 动态 framework 中使用, 才能获取到动态库的路径, 而 静态 framework 会返回 app 的根目录.
以加载 UnityApi.framework 库中根目录下的 loading.bundle 为例
动态 framework 获取路径
1
2
3NSBundle *fwBundle = [NSBundle bundleForClass:[UnityPlugin class]]; // UnityPlugin 是 UnityApi.framework 中随便的一个可访问的类
NSString *resPath = [fwBundle pathForResource:@"loading" ofType:@"bundle"];
NSBundle *resBundle = [NSBundle bundleWithPath:resPath];静态 framework 获取路径
1
2
3NSString *resPath = [[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:@"UnityApi.framework/loading.bundle"]; // 显式指定 库名
NSBundle *resBundle = [NSBundle bundleWithPath:resPath];
// privateFrameworksPath 就是 Frameworks, ios 的 framework 都是放在 Frameworks目录下
以上两个获取到的 resPath 都是 /data/Containers/Bundle/Application/1961B340-16FC-4F38-BBBA-98532919E2EB/MyIosTest.app/Frameworks/UnityApi.framework/loading.bundle
踩坑
build settings 配置要和 引用这个库的 一致
cpu 架构一致, 如: 都是 architecures armv7 arm64, 不然报错: one or more
目标版本一致, 如: 都是 ios developement target 9.0
framework 添加资源要以 group 方式, 不能是 folder
如果是 folder 方式, 编译会报错: Command CodeSign failed with a nonzero exit code