iOS动态库和静态库的运用
概念认识
什么是库
- 库是共享程序代码的方式,库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。在开发过程中,一些核心技术或者常用框架,出于安全性和稳定性的考虑,不想被外界知道,所以会把核心代码打包成库,只暴露出头文件以供使用。
- 库分为静态库和动态库两种。
- 静态库:链接时完整地拷贝至可执行文件中,使可执行文件体积变大。如果多个APP都使用了同一个静态库,那么每个APP都会拷贝一份。
- 动态库:链接时不拷贝至可执行文件中,可执行文件只会存储指向动态库的引用。程序运行时由系统动态加载到内存中,系统只会加载一次, 多个APP共用一份。
- 静态库的存在形式有两种:.a静态库、.framework静态库
- 动态库的存在形式有两种:.dylib动态库、系统的.framework动态库
系统的.framework是系统SDK库,有Foundation.framework、UIKit.framework、MapKit.framework等。由于苹果不开源,每个框架只提供了接口(.h文件),所有实现(.m文件或.c/.cpp文件)编译在一个.framework二进制文件中。
苹果把所有系统的.framework二进制文件统一打包成dyld_shared_cache_arm64文件和dyld_shared_cache_armv7文件,存储在手机路径(需要越狱才能找到):/System/Library/Caches/com.apple.dyld目录下。
动态链接器存储在手机路径:/usr/lib/dyld,用于在APP运行时,链接APP和系统的.framework。
两种.framework区别
- 静态库的形式包含.a和.framework两种形式,动态库的形式包含.dylib和系统的.framework两种形式。
动态库的.framework是系统SDK才有的库,而我们自己创建出来的.framework都是静态库
静态库中.a与.framework的区别
- .a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。
.a文件不能直接使用,需要.h文件配合。
.framework文件可以直接使用,因为本身包含了.h文件和资源文件。
.framework = .a + .h + sorrceFile(资源文件)
静态库的优点
- 实现程序的模块化,将固定的业务模块化成静态库。
- 方便共享代码,即可以和别人分享你的代码库,但别人又看不到你代码的实现。
- 开发第三方sdk的需要,例如两个公司之间业务交流,不可能把源代码都发送给另一个公司,这时候将私密内容打包成静态库,别人只能调用接口,而不能知道其中实现的细节。
编译链接
- 源代码转成目标文件的过程:
源代码先经过预处理器进行宏替换、删除注释等工作,得到.i文件,然后编译器对.i文件进行编译,编译成汇编语言程序(扩展名.s或.asm),之后再将汇编语言程序编译成机器指令(0和1组成),得到目标文件(扩展名.o)。 - 编译器和链接器处理流程:
源代码(.c或.cpp)→编译器→目标文件(.object)→链接器(+静态库)→可执行文件(.exe或Mach-O) - 链接器作用:
对于静态库,在编译链接时把多个目标文件和所用到的库文件链接在一起形成一个完整的可执行文件,可执行文件会比较大,但程序运行时就不需要库了。
对于动态库,在编译链接时把多个目标文件链接成可执行文件,但不会把库文件加入到该可执行文件中,而是在程序运行时链接库文件。
静态库制作
制作.a静态库
- .a文件是一种静态库,a是archive(归档)的缩写,它是由多个.o文件归档而成
- 新建工程,iOS --> Framework & Library --> Cocoa Touch Static Library
这里注意由于创建的是Static Library,Build Settings搜索linking,Mach-O Type默认为Static Library。
- 删除不需要的类,如StaticLibraryTool类,创建我们所需的类,如下:
- 添加需要公开的头文件
- 设置静态库需要支持的最低系统版本
- 修改配置 Active Architecture Only修改为NO,否则生成的静态库就只支持当前选择设备的架构。
- 接下来可以开始编译生成.a文件了。
设备选择Generic iOS Device,即通用型真机,然后command+B编译,在工程Products目录下生成.a文件,右键Show in Finder找到.a文件所在路径,图示Products目录下的libStaticLibraryTool.a从红色(红色表示文件不存在)变成了黑色(黑色表示文件存在),此时表示提供真机使用的静态库编译成功。
接着设备切换选择任一模拟器,command+B编译,此时提供模拟器使用的静态库编译成功,如下:
这两个.a文件要么只支持真机,要么只支持模拟器,如果想真机和模拟器都能使用该静态库,需要将二者合成为一个静态库,可用终端命令实现:
lipo -create 第一个.a文件路径 第二个.a文件路径 -output 最终的.a文件路径
合成为一个静态库后,我们可查看合成后的静态库支持的架构,用命令:lipo -info xxx.a
,看真机和模拟器架构是否都支持。结果如下:
“i386 x86_64”是模拟器架构,“armv7 arm64 ”是真机架构,说明该静态库两者都支持。
静态库支持哪些架构?
模拟器架构
iPhone4s ~ 5 : i386
iPhone5s ~ 7Plus : x86_64
真机架构
3GS~4s : armv7
5/5c : armv7s(armv7兼容armv7s)
5s ~ 6sPlus : arm64
- 如何使用.a静态库?
把.a文件和公开的头文件放入一个文件夹,命名为libStaticLibraryTool。将libStaticLibraryTool文件夹添加到需要使用的工程中,如下:

libStaticLibraryTool.a添加到工程后,
Build Pases->Link Binary With Libraries 和 General->Frameworks, Libraries, and Embedded Content都会自动引入libStaticLibraryTool.a。
Build Settings->Library Search Paths也会自动设置.a文件路径,如:$(PROJECT_DIR)/DemoA/libStaticLibraryTool。
由于静态库中使用了OC的分类(Category),OC链接器只会为类建立符号表,不会为分类建立符号表,导致函数调用时(运行时)找不到分类的符号表,无法获取函数地址,函数调用失败。
解决办法:设置Other Linker Flags的值为-ObjC,为分类建立符号表。
注意:如果不做该设置,项目中引用该库,访问该库的Category接口时会崩溃
最后我们便能在项目中引入头文件,使用.a静态库的功能了,如下:
- Xcode13制作静态库,左侧的Products目录不见了,其实Products是存在的,只是没有展示出来。
解决方式:对.xcodeproj右键“显示包内容”,打开project.pbxproj,command+f搜索mainGroup,复制mainGroup的值,将其粘贴到productRefGroup的值上,使两者保持一致,这样工程左侧的Products目录就显示出来了。
制作.framework静态库
- 新建工程时选择Framework
该Framework默认是Dynamic Library(动态库),我们需要将其设置成静态库:Build Settings搜索mach,Mach-O Type选择Static Library。
往工程中添加Person类和UIImage+Extension类,StaticLibraryTool.h中引入Person类和UIImage+Extension类的头文件,推荐用包含静态库名的尖括号,指明引入的是哪个静态库的头文件:
Person.h和UIImage+Extension.h需要暴露出来,这两个头文件默认在TARGETS->Build Phases->Headers的Project中,将它们拖拽到Headers的Public中,如下:
设置Build Settings中的Active Architecture Only为NO,iOS Deployment Target的最低版本为iOS 9.0,然后command+B,编译生成.framework静态库。
- 如何使用.framework静态库?
使用时,将StaticLibraryTool.framework拖入到需要使用的工程中。
Build Settings->Other Linker Flags设置-ObjC,以便编译器能加载OC的Category(若不配置这个,访问Category的接口时程序会崩溃)。
由于静态库StaticLibraryTool.h中引入的头文件带上了静态库名作为路径,即如下方式
#import <StaticLibraryTool/Person.h>
#import <StaticLibraryTool/UIImage+Extension.h>
因此Build Settings->Header Search Paths可不用设置静态库StaticLibraryTool的路径。
使用静态库时,用以下方式:
//#import <StaticLibraryTool/StaticLibraryTool.h> 或以下
#import <StaticLibraryTool/Person.h>
#import <StaticLibraryTool/UIImage+Extension.h>
如果想用冒号引入:#import "StaticLibraryTool.h"(不推荐,无法明确这是静态库的头文件),则需要配置Header Search Paths,添加路径:$(PROJECT_DIR)/DemoA/StaticLibraryTool.framework/Headers
实现静态库的注意事项
- 无论是.a静态库还是.framework静态库,我们需要的都是二进制文件+.h文件+资源文件,不同的是,.a本身只是二进制文件,需要配上.h文件和资源文件才能使用,而.framework本身已经包含了二进制文件、.h和资源文件,可以直接使用。
- 图片资源的处理:两种静态库,一般都是把图片文件单独的放在一个.bundle文件中,一般.bundle的名字和.a或.framework的名字相同。新建一个文件夹,把它改名为.bundle,右键->显示包内容,之后就可以向其中添加资源文件。
- 把category打成静态库,在使用静态库的工程中,调用category中的方法时会报找不到该方法的错误(selector not recognized),解决办法是:在使用静态库的工程中配置Build Settings->Other Linker Flags的值为-ObjC。
- 如果一个静态库很复杂,需要暴露的.h文件比较多,则可以在静态库的内部创建一个.h文件(这个.h文件的名字一般和静态库的名字相同)统一管理,把所有需要暴露出来的.h文件都集中放在这个.h文件中,这样使用时可以只引入该.h文件。
iOS动态库和静态库的运用的更多相关文章
- 【转】iOS动态库和静态库的简要介绍
静态库与动态库的区别 首先来看什么是库,库(Library)说白了就是一段编译好的二进制代码,加上头文件就可以供别人使用. 什么时候我们会用到库呢?一种情况是某些代码需要给别人使用,但是我们不希望别人 ...
- ios 开发中 动态库 与静态库的区别
使用静态库的好处 1,模块化,分工合作 2,避免少量改动经常导致大量的重复编译连接 3,也可以重用,注意不是共享使用 动态库使用有如下好处: 1使用动态库,可以将最终可执行文件体积缩小 2使用动态库, ...
- iOS开发拓展篇—静态库
iOS开发拓展篇—静态库 一.简单介绍 1.什么是库? 库是程序代码的集合,是共享程序代码的一种方式 2.库的分类 根据源代码的公开情况,库可以分为2种类型 (1)开源库 公开源代码,能看到具体实现 ...
- 【转】iOS开发拓展篇—静态库
原文网址:http://www.cnblogs.com/wendingding/p/3893095.html iOS开发拓展篇-静态库 一.简单介绍 1.什么是库? 库是程序代码的集合,是共享程序代码 ...
- iOS实用技能扩展-静态库的制作与简单使用
前言:此文是关于静态库的概念描述,如何制作及简单调试使用,不同版本的说明与场景使用. 1.关于库的简介: 库可以分为2种类型 开源库 公开源代码,能看到具体实现 比如SDWebImage.AFNetw ...
- Linux中的动态库和静态库(.a/.la/.so/.o)
Linux中的动态库和静态库(.a/.la/.so/.o) Linux中的动态库和静态库(.a/.la/.so/.o) C/C++程序编译的过程 .o文件(目标文件) 创建atoi.o 使用atoi. ...
- Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf 动态库的后缀为*.so 静态库的后缀为 libxxx.a ldconfig 目录名
Linux系统中“动态库”和“静态库”那点事儿 /etc/ld.so.conf 动态库的后缀为*.so 静态库的后缀为 libxxx.a ldconfig 目录名 转载自:http://b ...
- Linux系统中“动态库”和“静态库”那点事儿【转】
转自:http://blog.chinaunix.net/uid-23069658-id-3142046.html 今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻. ...
- libjpeg 交叉编译动态库和静态库
1.下载libjpeg库,解压之 得到了jpeg6b和libtool-2.2.4两个文件夹. 2.编译安装libtool工具. 这是配置libtool,这里需要注意:configure 参 ...
随机推荐
- 全网最全的Java SpringBoot点赞功能实现
前言 最近公司在做一个NFT商城的项目,大致就是一个只买卖数字产品的平台,项目中有个需求是用户可以给商品点赞,还需要获取商品的点赞总数,类似下图 起初感觉这功能很好实现,无非就是加个点赞表嘛,后来发现 ...
- 使用Hot Chocolate和.NET 6构建GraphQL应用(2) —— 实体相关功能实现
系列导航 使用Hot Chocolate和.NET 6构建GraphQL应用文章索引 需求 在本文中,我们将会准备好用于实现GraphQL接口所依赖的底层数据,为下一篇文章具体实现GraphQL接口做 ...
- IEEE754浮点数表示法
IEEE二进制浮点数算术标准(ANSI/IEEE Std 754-1985)是一套规定如何用二进制表示浮点数的标准.就像"补码规则"建立了二进制位和正负数的一一对应关系一样,IEE ...
- TCP Wrappers
TCP Wrappers 是 RHEL 7 系统中默认启用的一款流量监控程序,它能够根据来访主机的地址与本机的目标服务程序作出允许或拒绝的操作.换句话说,Linux 系统中其实有两个层面的防火墙,第一 ...
- nohub命令简单介绍。
/* 来自对 https://www.cnblogs.com/kexianting/p/11628983.html 编辑. 一 什么是 nohub? 1 是 no hang up 的缩写,就是不挂断的 ...
- 计算机网络再次整理————tcp例子前奏[三]
前言 简单编写一下tcp例子. 正文 我们常说IOS有7层,实际上也只有4层,或者这样说简单的说是4层. 首先是数据链路层,首先这一层解决了什么问题呢?为什么要有这一层呢? 首先要抛开有操作系统的意识 ...
- C++的set重载运算符
转载: https://www.cnblogs.com/zhihaospace/p/12843802.html set 容器模版需要3个泛型参数,如下: template<class T, cl ...
- 海康NVR设备上传人脸图片到人脸库
海康开放平台--海康文档链接--海康开发包和文档下载链接 硬件:海康超脑NVR(全称Network Video Recorder,即网络视频录像机).人脸摄像机. 环境:JDK_1.8 Windows ...
- Matplotlib 3.0 秘籍·翻译完成
原文:Matplotlib 3.0 Cookbook 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远. 在线阅读 ApacheCN 面试求职交 ...
- ABC209 E Shiritori
考虑对这个问题进行转化: 显然我们只关注每个串前三个棋子和后三个棋子,并且根据题目的特性,我们可以将任意的三个字符看作点,将一个字符串看作连接两个点的边,这样我们得到了一张点数为 \(52 ^ 3\) ...