概念认识

什么是库

  • 库是共享程序代码的方式,库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。在开发过程中,一些核心技术或者常用框架,出于安全性和稳定性的考虑,不想被外界知道,所以会把核心代码打包成库,只暴露出头文件以供使用。
  • 库分为静态库和动态库两种。
    • 静态库:链接时完整地拷贝至可执行文件中,使可执行文件体积变大。如果多个APP都使用了同一个静态库,那么每个APP都会拷贝一份。
    • 动态库:链接时不拷贝至可执行文件中,可执行文件只会存储指向动态库的引用。程序运行时由系统动态加载到内存中,系统只会加载一次, 多个APP共用一份。
  • 静态库的存在形式有两种:.a静态库、.framework静态库
  • 动态库的存在形式有两种:.dylib动态库、系统的.framework动态库

系统的.framework是系统SDK库,有Foundation.framework、UIKit.framework、MapKit.framework等。由于苹果不开源,每个框架只提供了接口(.h文件),所有实现(.m文件或.c/.cpp文件)编译在一个.framework二进制文件中。

苹果把所有系统的.framework二进制文件统一打包到一个共享缓存文件中(dyld shared cache),共享缓存文件存储在手机路径(需要越狱才能找到):/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX。X代表ARM处理器指令集架构。

动态链接器(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文件要么只支持真机,要么只支持模拟器,如果想真机和模拟器都能使用该静态库,需要将二者合成为一个静态库,可用终端命令实现: ```objc lipo -create 第一个.a文件路径 第二个.a文件路径 -output 最终的.a文件路径 ```

合成为一个静态库后,我们可查看合成后的静态库支持的架构,用命令:lipo -info xxx.a,看真机和模拟器架构是否都支持。结果如下:

"i386 x86_64"是模拟器架构,"armv7 arm64"是真机架构,说明该静态库两者都支持。 静态库支持哪些架构?

模拟器架构iPhone4s ~ 5/5c : i386iPhone5s以后机型 : x86_64
真机架构3GS~4s : armv75/5c : armv7s(armv7兼容armv7s)5s ~ iPhoneX : arm64iPhone XS以后机型 : arm64e
  • 如何使用.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中引入的头文件带上了静态库名作为路径,即如下方式 ```c #import

实现静态库的注意事项

  • 无论是.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动态库和静态库的运用相关推荐

  1. ios 开发中 动态库 与静态库的区别

    使用静态库的好处 1,模块化,分工合作 2,避免少量改动经常导致大量的重复编译连接 3,也可以重用,注意不是共享使用 动态库使用有如下好处: 1使用动态库,可以将最终可执行文件体积缩小 2使用动态库, ...

  2. iOS之深入解析静态库和动态库

    一.库 ① 什么是库? 库就是程序代码的集合,将 N 个文件组织起来,是共享程序代码的一种方式. 从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行. ② 库的分类 根据程序代码的开源情况 ...

  3. iOS SDK开发系列一之Cocoapods原理,Xcode的配置,动态库和静态库介绍

    前言 三个月没写东西了,是时候总结点东西了.SDK这个东西开发其实和项目开发类似,但是项目中你不需要关注一些配置和打包的参数,或者你压根不需要关注Framework和.a到底是怎么链接配置的,因为Co ...

  4. 深入iOS系统底层之静态库介绍

    少长咸集,群贤毕至.--<王羲之・兰亭集序> 目标文件 目标文件结构 程序员编写的是源代码,而计算机运行的则是CPU能识别的机器指令,因此必须要有一系列工具或程序来将源代码转化为机器指令, ...

  5. oc 协议 回调 静态成员_深入iOS系统底层之静态库

    少长咸集,群贤毕至.--<王羲之・兰亭集序> 目标文件 目标文件结构 程序员编写的是源代码,而计算机运行的则是CPU能识别的机器指令,因此必须要有一系列工具或程序来将源代码转化为机器指令, ...

  6. iOS入门之打包静态库

    在项目开发中,或多或少的都会使用第三方库,有时候也会将自己项目中独立于业务的相关代码打包成库以供别人使用.在Android开发中,一般打包为aar或者jar文件以供第三方使用.iOS开发中,则可以直接 ...

  7. linux代码动态分析软件,举例分析Linux动态库和静态库

    函数库分为静态库和动态库两种.创建Linux静态库和Linux动态库和使用它们在这里将以举例的形式详述一下.静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.动态库在程序编译时并不 ...

  8. Linux动态库和静态库比较

     Linux动态库和静态库比较文件预览 文件目录树如下,如你所见,非常简单.    1. libtest/    2. |-- lt.c    3. |-- lt.h    4. `-- test.c ...

  9. Linux中的动态库和静态库(.a/.la/.so/.o)

    为什么80%的码农都做不了架构师?>>>    Linux中的动态库和静态库(.a/.la/.so/.o) Linux中的动态库和静态库(.a/.la/.so/.o) C/C++程序 ...

  10. iOS开发拓展篇—静态库

    一.简单介绍 1.什么是库? 库是程序代码的集合,是共享程序代码的一种方式 2.库的分类 根据源代码的公开情况,库可以分为2种类型 (1)开源库 公开源代码,能看到具体实现 比如SDWebImage. ...

最新文章

  1. 「二分查找」之我见!今天刷一道leetcode算法!
  2. (正确姿势)centos7 如何从U盘拷贝文件
  3. 对Linux Kernel 4.15的支持的VirtualBox 5.2.8发布
  4. 编辑器js获取浏览器高度和宽度值(转)
  5. application/json 四种常见的 POST 提交数据方式
  6. 2012年12月第二个周末
  7. 理解点击屏幕的事件响应---对UIView的hitTest: withEvent: 方法的理解
  8. java Queue
  9. 崚 不能被 iconv(gb2312,utf-8 ,string)
  10. paip.cache 缓存架构以及性能提升总结
  11. python类的本质和跨文件全局变量(秒杀单例模式)
  12. HW-RTOS 概述
  13. 图灵测试 Alan Turning
  14. 实现用户行为监测之webfunny
  15. 即时热榜——月薪3W+自媒体人的必备神器
  16. android 长按保存图片,安卓机上base64图片无法在微信中长按保存?
  17. VCRedist.exe静默安装方法(转)
  18. Sql Server 2008 通用语法总结
  19. 计算机技术协会主持词,协会表彰大会主持词
  20. 如何用js进行日期的加减(天数)?

热门文章

  1. oracle 客户端 ora-12162,oracle 连接不上ORA-12162: TNS:net service name is incorrectly specified的另外一种可能原因...
  2. 安捷伦色质谱仪维修四极杆驱动器维修G2571
  3. 地址总线、数据总线、控制总线详解
  4. linux服务器查sn,命令查看服务器SN号
  5. C++模板编程(18)---模板实例化instantiation
  6. 三维空间中向量的旋转
  7. javaScript、PHP连接外卖小票机打印机方案(佳博、芯烨等)
  8. Flask 数据库迁移(详解)
  9. 【postgres】postgres 数据库迁移
  10. Halcon测量圆直径(半径)的方法之暴力拟合法 vs 测量工具法