iOS-静态库、动态库

库是共享代码的方式,根据源代码的公开情况,库可以分为两种类型:

  1. 开源库
    公开源代码,能看到具体实现,比如SDWebImage、AFNetworking。
  2. 闭源库
    不公开源代码,是经过编译后的二进制文件,看不到具体实现。
    主要分为:静态库、动态库
  • 静态库:
    1、平时我们用的第三方SDK基本上都是静态库。
    2、静态库在项目编译时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
    3、静态库很大的一个优点是减少耦合性,因为静态库中是不可以包含其他静态库的,使用的时候要另外导入它的依赖库,最大限度的保证了每一个静态库都是独立的,不会重复引用。
    4、静态库有.a 和 .framework两种形式。

  • 动态库:
    1、iOS平时使用的系统库基本是动态库,比如使用频率最高的UIKit.framework和Fundation.framework。
    2、动态库在程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。
    3、动态库在制作的时候可以直接包含静态库,也能自动link所需要的依赖库。
    4、动态库有.dylib/.tbd、.framework两种形式。
    5、苹果禁止iOS开发中使用动态库。

  • .a与.framework有什么区别?
    1、.a是一个纯二进制文件,.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。
    2、.a + .h + sourceFile = .framework。
    3、自己封装静态SDK建议用.framework。

一. 静态库(.a)

1、静态库(.a)的制作

  1. shift + command + n 创建项目,选择 Static Library
Static Library.png
  1. 输入静态库名称
名称.png
  1. 添加代码

在生成文件中写如下代码:
StaticDemo1.h文件:

#import <UIKit/UIKit.h>

@interface StaticDemo1 : NSObject

- (UIImage *)getImage1;

@end

StaticDemo1.m文件:

#import "StaticDemo1.h"

@implementation StaticDemo1

- (UIImage *)getImage1 {
    UIImage *ima = [UIImage imageNamed:@"StaticDemo1.bundle/美女1.png"];
    return ima;
}
@end

注意:静态库中代码引用资源推荐下面这种方式:

UIImage *ima = [UIImage imageNamed:@"StaticDemo1.bundle/美女1.png"];
  1. 选择需要暴露出来的.h文件,.m文件会自动编译到.a文件中
添加头文件.png

设置为public:

移动到public.png
  1. 修改Build Settings中的 Build Active Architecture Only 为NO 以满足运行不同CPU环境的模拟器
设置为NO.png
  1. 编译

分别切换真机、模拟器,然后command + b编译,右键Show in Finder

Show in Finder.png

生成的文件如下:

生成的文件.png

编译之后红色会变色白色,如下:

白色.png
  1. 合并静态库

cd到Products目录,在终端执行如下命令:

lipo -create 静态库1路径 静态库2路径 -output 新静态库名称.a

合并Debug-iphoneos和Debug-iphonesimulator文件夹下的StaticDemo1.a文件,如下图:

合并.png

合并完成后如下:

合并完成.png

在终端使用如下命令,查看静态库支持的运行环境:

lipo -info 静态库路径 

结果:

结果.png

可以发现,x86_64(模拟器)和arm64(真机)都支持。

  1. 制作bundle

① 如果静态库中用到了图片资源,一般都放到一个bundle文件中,bundle名字一般跟 .a 或 .framework 名字一致。
② bundle的创建:新建一个文件夹,修改扩展名为 .bundle 即可,右击bundle文件,显示包内容,就可以往bundle文件中放东西。
③ 自己制作的静态库中要用到的图片资源,不建议直接拖到项目中使用,而是推荐放到bundle文件中,这样可以避免静态库的图片名和使用静态库的项目中存在的图片产生冲突。

  1. 完成

将上面合成后的StaticDemo1.a和下图随便一个文件夹的头文件,以及上面制作的bundle文件夹放到一起。

头文件.png

至此,.a静态库制作完成。

完成.png

其他问题:

  1. 头文件
    如果静态库需要暴露出来的 .h 比较多,可以考虑创建一个主头文件(一般主头文件和静态库同名)。
    ① 在主头文件中包含所有其他需要暴露出来的 .h 文件
    ② 使用静态库时,只需要#import 主头文件
    ③ 实际上苹果官方就是这么做的,例如:#import <UIKit/UIKit.h>

  2. 静态库中包含了Category(分类)
    如果静态库中包含了Category,有时候在使用静态库的工程中会报“方法找不到”的错误(unrecognized selector sent to instance)。
    解决方案:在 Build Settings --> Other Linker Flags中加 -Objc。

2、.a静态库的使用

  1. 将.a、.h、资源文件拖拽到项目中
  2. 引入#import "StaticDemo1.h"头文件就可以使用了,结果如下:
使用.png

二. 静态库(.framework)

  1. 静态库(.framework)和静态库(.a)的制作类似,所以下面的步骤以描述为主。
  2. 动态库(.framework)与静态库(.framework)的制作流程基本一样,唯一不同的是Mach-O文件的编译形式。

1、静态库(.framework)的制作

  1. shift + command + n 创建项目,选择Framework
  2. 输入静态库名称:StaticDemo2
  3. 添加代码

我们这次做稍微复杂一点,新建StaticDemo2Custom类,在这个类中,不但有自己的代码还使用了上面我们刚刚制作的StaticDemo1.a的代码。

① 首先导入刚才制作的StaticDemo1.a文件和.h头文件,不勾选Add to targets,如下:

不勾选.png

② 如果你用到的第三方静态库需要依赖其他系统库的话,需要在导入第三方静态库之后再link依赖的系统库

link.png

③ 新创建类具体实现如下:
StaticDemo2Custom.h文件:

#import <UIKit/UIKit.h>

@interface StaticDemo2Custom : NSObject

- (UIImage *)customGetImage1;

- (UIImage *)customGetImage2;

@end

StaticDemo2Custom.m文件:

#import "StaticDemo2Custom.h"
#import "StaticDemo1.h"

@implementation StaticDemo2Custom

- (UIImage *)customGetImage1 {
    //使用StaticDemo1.a的代码
    UIImage *image = [[[StaticDemo1 alloc] init] getImage1];
    return image;;
}

- (UIImage *)customGetImage2 {
    //自己的代码
    UIImage *ima = [UIImage imageNamed:@"StaticDemo2.bundle/美女2.png"];
    return ima;
}
@end

目录结构:

目录结构.png
  1. 设置Mach-O Type为Static Library,如下:
设置Static Library.png
  1. 选择需要暴露出来的.h文件

然后需要在StaticDemo2.h(StaticDemo2.h必须放在Public里)中将你所有要公开的.h引入。

头文件.png
  1. 修改Build Settings中的 Build Active Architecture Only 为NO 以满足运行不同CPU环境的模拟器
  2. 分别切换真机、模拟器,然后command + b编译,右键Show in Finder
Show in Finder.png
  1. 合并静态库

cd到Products目录,在终端执行如下命令:

lipo -create 静态库1路径 静态库2路径 -output 新静态库名称

注意:这里合并的是StaticDemo2.framework下的StaticDemo2,合并完成后将新的文件替换原来的StaticDemo2,就得到新的StaticDemo2.framework,至此静态库(.framework)制作完成。

2、静态库(.framework)的使用

  1. 由于我们的静态库(.framework)使用了其他静态库,所以需要导入其他静态库以及它的资源文件,如下:
目录结构.png
  1. 导入头文件
#import <StaticDemo2/StaticDemo2.h>
  1. 编写测试代码,运行,结果如下:
结果.png

可以发现,无论是静态库(.framework)的代码,还是其他静态库的代码,执行都没问题。

自动合成静态库(推荐)

上面都是手动合成静态库,很麻烦,下面介绍一下脚本合成的方法,推荐使用这种方式。

  1. 选中项目,点击导航栏上的Editor,选择Add Target创建一个Aggregate。
Aggregate.png
  1. 选中刚刚创建的Aggregate,然后选中右侧的Build Phases,点击左下方加号,选择New Run Script Phase。
Script规则.png
  1. 嵌入脚本
#这个是声明生成的framework的名字,有些和工程名字一样,看你创建时候怎么写
#FMK_NAME是个变量
FMK_NAME=${PROJECT_NAME}
if [ "${ACTION}" = "build" ]
then
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${FMK_NAME}.framework
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
#ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
#这个是合并完成后打开对应的文件夹,你就可以直接看到文件了
open "${SRCROOT}/Products"
fi

如下:

脚本.png
  1. 模拟器和真机都编译生成framework

这一步一定不能漏掉,因为只有先生成模拟器和真机的framework之后才可以合并。

  1. 选中MyScript,设备选 Generic iOS Device,点击运行,如果有跳到Finder说明编译成功(运行脚本就是将模拟器和真机的framework合并成通用的framework),如下:
结果.png

生成的StaticDemo2.framework就可以直接使用了。

参考链接:
【iOS】静态库(.framework)制作
静态库与动态库制作

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342