iOS SDK开发 静态库 动态库

0 阅读3分钟

SDK分为静态库和动态库。

在日常开发中,静态库和动态库对我们开发影响不大。

如果开发app扩展,静态库会分别在主APP和拓展APP都有一份。这样APP的包体积会变大。

动态库可以让主APP和扩展APP都引用同一份。

静态库的开发。

image.png

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。

image.png

Command+b 编译。在Product目录下,可以选择Show Build Folder in Finder。查看编译后的路径并打开这个文件夹。

image.png

把Build,Products,Debug-iphoneos包的.a文件就是真机的静态库文件。

image.png

然后再编译真机调试的版本。

image.png

这样就会有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真机的静态库地址。

image.png

同时,设置Library Search Path。

image.png

2个静态库的处理方案2:推荐

打包成XCFramework。

把真机.a + 模拟器.a + 头文件打包成XCFramework,拖进项目,Xcode自动根据目标平台选择对应切片,不用手动写条件

image.png

2个静态库的处理方案3:

静态库源码就在当前工程里。适合自己写的静态库,调试贼舒服。

你的项目里同时存在静态库 Target(MyStaticLibrary)和扩展 Target(OpenGL Share)

  1. 进入扩展 Target → Build Phases → Target Dependencies,添加 MyStaticLibrary
  2. 扩展 Target 的 Link Binary With Libraries 不要手动加.a Xcode 在编译扩展的时候,自动根据当前目标(真机 / 模拟器)自动编译对应平台版本的静态库,并且自动链接对应.a。 ✅ 开发调试最舒服,不用手动管理.a 文件,不用手动打包 xcframework。

静态库的加载。

以XCFramework为例。

image.png

image.png

如果程序中没有使用这个静态库的内容,哪怕import引入了,也不会打包到项目中。runtime直接找不到这个类。

image.png

如果要实现虽然没有使用,但是runtime要能找到,则必须设置Other Linker Flags

image.png

注意顺序不能反。否则失效。

$(inherited)
-force_load
$(BUILT_PRODUCTS_DIR)/libMyStaticLibrary.a

再次执行就发现可以使用了

image.png

总结

模式 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编码后写入到代码中。