iOS开发中『库』的区别与应用

iOS开发中『库』的区别与应用

前言

在iOS开发中你肯定听说过.framework.a.tbd.dylib那么这都是啥?那个是静态库?那个是动态库?

1.编译过程

首先我们先了解一下编译过程,这有助于我们对「库」的理解。

1.1 编译过程中的几个步骤

当我们开始build后我们的IDE究竟为我们做了什么事情呢?

  • 预处理(Pre-process)

预编译阶段是把宏替换,删除注释,展开头文件,产生 .i 文件。

  • 编译(Compliling)

编译阶段是把之前的 .i 文件转换成汇编语言,产生 .s文件。

  • 汇编(Asembly)

汇编阶段是把汇编语言文件转换为机器码文件,产生 .o 文件。

  • 链接(Link)

连接阶段是对.o文件中的对于其他的库的引用的地方进行引用,生成最后的可执行文件(同时也包括多个 .o 文件进行 link)。

1.2 编译选项

  • Build phases

主要是用来控制从源文件到可执行文件的整个过程的,所以说应该是面向源文件的,包括编译那些文件,以及在编译过程中执行一些自定义的脚本。

  • Build rules

主要是用来控制如何编译某种类型的源文件,例如相对某种类型的源文件进行特定的编译就应该在这里进行编辑了,同时也会大量的运用一些Xcode中的环境变量。

官方文档传送门:Build Setting Reference

查看Xcode中所有环境变量:
终端->export OBJC_HELP=1

Xcode env.jpg
  • Build settings

主要是对编译工作的细节设定,在这个窗口中可以看见大量的选项,从编译到打包再到代码签名应有尽有,这里要注意 settingssection 分类,同时一般通过右侧的 inspector 就可以很好的理解选项的意义了。

2. 动态库&静态库

Static frameworks are linked at compile time. Dynamic frameworks are linked at runtime. 静态库在编译期间进行链接,动态库在运行时进行链接。

不管是动态库还是静态库都是「库」也就是编译好的二进制文件,它们的区别在于用法,那么为什么还要区分动态和静态呢?请看下图:

Static frameworks.jpg
Dynamic frameworks.jpg
  • 静态库

对于静态库而言,在编译链接的时候,会将静态库被使用的文件合并到目标APP可执行文件中,其实静态库只参与了链接过程,因为它本身就是被编译好了的.o文件。

静态库链接过程

  • 连接器会将所有.o用到的global symbolunresolved symbol放入到一个临时表,而且global symbol是不能重复的。

  • 对于静态库的.o链接器会将没有任何symbolunresolved symbol table忽略

  • 最后,连接器会将函数的引用替换为其实际的实现地址

  • 动态库

首先,对于动态库其实分为动态链接库动态加载库两种,这两个的本质区别还是加载时间。

  • 动态链接库:在没有被加载到内存的前提下,当可执行文件被加载,动态库也随着被加载到内存中。
  • 动态加载库:当需要使用的时候通过命令进行加载,例如dlopen

小结:

  1. 静态库和动态库都是二进制文件
  2. 静态库在编译连接期间就会被合并的可执行文件中
  3. 动态库可能随着可执行文件的加载而加载,也可能在被使用的时候通过命令加载
  4. 动态库由于加载延后所以启动和加载会更耗时
  5. 在iOS中苹果通过共享缓存技术来实现UIKitFoundationCFNetwork等等库的加载,同时也减少了APP包的体积

3. 不同后缀库的区别

3.1 .framework & .a

  • .a是一个纯二进制文件,需要配合头文件,资源文件一起使用,在iOS中一般用作静态库文件的后缀名。
  • 。framework中除了有二进制文件还有资源文件,可以直接使用
  • 在不能开发动态库的时候,其实framework = .a + .h + .bundle,在Xcode6以后,我们可以开发动态库了, framework = 静态库/动态库 + .h + .bundle

3.2 .tbd & .dylib

  • .dylib是动态库常用的后缀名,我们主要见过的地方就是libsqlite3.dylib
  • Xcode 7以后我们在导入系统提供的动态库的时候不再有.dylib了,取而代之的是.tbd
  • .tbd是一个YAML文本文件,描述了需要连接的动态库信息,主要目的还是为了减少app的下载大小

那么为什么要这样做呢?以下是Stackoverflow上的一篇回答

You can also see a .tbd file if you go to the General tab of your Xcode project and then add a library under Linked Frameworks and Libraries. The .tbd file will be copied to your project.

So it appears that the .dylib file is the actual library of binary code that your project is using and is located in the /usr/lib/ directory on the user's device. The .tbd file, on the other hand, is just a text file that is included in your project and serves as a link to the required .dylib binary. Since this text file is much smaller than the binary library, it makes the SDK's download size smaller.

如果转到Xcode项目的General选项卡,然后在链接框架和库下添加一个库,还可以看到一个.tbd文件。tbd文件将被复制到您的项目中。

因此,.dylib文件似乎是项目使用的二进制代码的实际库,并且位于用户设备的/usr/lib/目录中。另一方面,.tbd文件只是一个包含在项目中的文本文件,用作所需的.dylib二进制文件的链接。因为这个文本文件比二进制库小得多,所以它使得SDK的下载大小更小。

4.总结

  1. 静态库主要是.a文件,也有.framework
  2. 动态库主要使用.dylib.tbd.framework作为后缀名
  3. 相对于静态库,动态库在包体积上占有绝对优势
  4. 在iOS上由于苹果做了优化,所以系统的动态库通过共享缓存技术启动很快,内存占用很少
  5. 但是我们自己开发的动态库将不会有4中的优势
  6. 从可用性来看.framework相对于.a在静态库上更有优势

5. 参考资料

iOS 开发中的『库』(一)
iOS 开发中的『库』(二)

你可能感兴趣的:(iOS开发中『库』的区别与应用)