SDK分为静态库和动态库。
在日常开发中,静态库和动态库对我们开发影响不大。
如果开发app扩展,静态库会分别在主APP和拓展APP都有一份。这样APP的包体积会变大。
动态库可以让主APP和扩展APP都引用同一份。
静态库的开发。
MyStaticLibrary.h
#import <Foundation/Foundation.h>
@interface MyStaticLibrary : NSObject
- (void) print1;
- (void) print2;
@end
MyStaticLibrary.m
#import "MyStaticLibrary.h"
@implementation MyStaticLibrary
- (void) print1{
NSLog(@"This is from MyStaticLibrary - (void) print1");
}
- (void) print2{
NSLog(@"This is from MyStaticLibrary - (void) print2");
}
@end
静态库分模拟器和真机。一次只能编译一个,然后再进行合并。
编译真机版本,选择Any iOS Device。
Command+b 编译。在Product目录下,可以选择Show Build Folder in Finder。查看编译后的路径并打开这个文件夹。
把Build,Products,Debug-iphoneos包的.a文件就是真机的静态库文件。
然后再编译真机调试的版本。
这样就会有2个版本的静态库了。
在老版本的Xcode,因为是intel平台,所以可以直接使用lipo -create Debug-iphoneos/libMyStaticLibrary.a Debug-iphonesimulator/libMyStaticLibrary.a -output ./libMyStaticLibrary.a将两份静态库进行合并。但是目前Mac电脑是M系列的ARM处理器,导致合并的时候会报错,会无法合并。
2个静态库的处理方案1:
分别引用2个静态库,在Other Linker Flags进行设置模拟器和iOS真机的静态库地址。
同时,设置Library Search Path。
2个静态库的处理方案2:推荐
打包成XCFramework。
把真机.a + 模拟器.a + 头文件打包成XCFramework,拖进项目,Xcode自动根据目标平台选择对应切片,不用手动写条件
2个静态库的处理方案3:
静态库源码就在当前工程里。适合自己写的静态库,调试贼舒服。
你的项目里同时存在静态库 Target(MyStaticLibrary)和扩展 Target(OpenGL Share)
- 进入扩展 Target → Build Phases → Target Dependencies,添加 MyStaticLibrary
- 扩展 Target 的 Link Binary With Libraries 不要手动加.a Xcode 在编译扩展的时候,自动根据当前目标(真机 / 模拟器)自动编译对应平台版本的静态库,并且自动链接对应.a。 ✅ 开发调试最舒服,不用手动管理.a 文件,不用手动打包 xcframework。
静态库的加载。
以XCFramework为例。
如果程序中没有使用这个静态库的内容,哪怕import引入了,也不会打包到项目中。runtime直接找不到这个类。
如果要实现虽然没有使用,但是runtime要能找到,则必须设置Other Linker Flags
注意顺序不能反。否则失效。
$(inherited)
-force_load
$(BUILT_PRODUCTS_DIR)/libMyStaticLibrary.a
再次执行就发现可以使用了
总结
模式 A:Link Binary With Libraries,不加 -force_load
- 代码完全不使用库:ld 跳过整个.a,.o 不进链接
- 代码使用库里面任意一个符号:ld 拉入对应的
.o;之后 Release 下 DEAD_CODE_STRIPPING 再剔除这个.o 里面不可到达的函数
模式 B:Link Binary With Libraries + -force_load
-
代码完全不使用库:强制把全部.o 拉入链接
-
拉入之后,再看 DEAD_CODE_STRIPPING:
- DEAD_CODE_STRIPPING=YES:链接器发现函数不可到达 → 删除代码
- DEAD_CODE_STRIPPING=NO:函数保留在 Mach-O,nm 能看到符号
DEAD_CODE_STRIPPING 只针对C的函数,OC的方法就算没有使用,也全部保留。
动态库
动态库 (dylib/framework) :不拷贝进主程序二进制,运行时才加载到内存。
动态库是导致加载的时候,dyld的时候多一次loadimages。因此不推荐。
动态库可以带资源文件,静态库不能带资源文件。
静态库可以单独新建一个Bundle文件,或者直接base64编码后写入到代码中。