当前位置:网站首页 > 编程语言 > 正文

动态库和静态库有什么区别(静态库和动态库的缺点)



静态库:链接时,静态库会被完整地复制到可执行文件中,被多次使用就有多份冗余拷贝(图1所示)

系统动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存(图2所示)

上图中的绿框表示app的可执行文件。

应用插件化:

一个功能点都是一个动态库,在用户想使用某个功能的时候让其从网络下载,然后手动加载动态库,实现功能的的插件化

虽然技术上来说这种动态更新是可行的,但是对于AppStore上上架的app是不可以的。iOS8之后虽然可以上传含有动态库的app,但是苹果不仅需要你动态库和app的签名一致,而且苹果会在你上架的时候再经过一次AppStore的签名。所以你想在线更新动态库,首先你得有苹果APPStore私钥,而这个基本不可能。

除非你的应用不需要通过AppStore上架,比如企业内部的应用,通过企业证书发布,那么就可以实现应用插件化在线更新动态库了。

共享可执行文件:

在其它大部分平台上,动态库都可以用于不同应用间共享,这就大大节省了内存。从目前来看,iOS仍然不允许进程间共享动态库,即iOS上的动态库只能是私有的,因为我们仍然不能将动态库文件放置在除了自身沙盒以外的其它任何地方。

不过iOS8上开放了App Extension功能,可以为一个应用创建插件,这样主app和插件之间共享动态库还是可行的。(还需了解下App Extension)

Xcode6之后苹果在iOS上开放了动态库。

创建:File->New->Project

创建

我们上面说过Framework即可以是动态库,也可以是静态库。那么我们上图中默认创建的是动态库,那么如何创建动态库呢?比如我创建的framework叫,然后在中设置动态库或静态库。如下图,创建framework的时候默认是,我们可以修改为。

如果我们创建的framework是动态库,那么我们直接在工程里使用的时候会报错:。需要在工程的里的添加这个动态库才能使用。 因为我们创建的这个动态库其实也不能给其他程序使用的,而你的和之间是需要使用这个动态库的。这个动态库可以和之间共用一份(App 和 Extension 的 Bundle 是共享的),因此苹果又把这种 Framework 称为 ,而我把这个动态库称为伪动态库

具体创建静态库和Framework可以参考:Xcode7创建静态库和Framework。

我们创建的动态库和系统的动态库有什么区别呢?我们创建的动态库是在我们自己应用的.app目录里面,只能自己的和使用。而系统的动态库是在系统目录里面,所有的程序都能使用。

可执行文件和自己创建的动态库位置:

一般我们得到的iOS程序包是.ipa文件。其实就是一个压缩包,解压缩.ipa。解压缩后里面会有一个payload文件夹,文件夹里有一个.app文件,右键显示包内容,然后找到一个一般体积最大跟.app同名的文件,那个文件就是可执行文件。 而我们在模拟器上运行的时候用就能得到.app的路径。可执行文件就在.app里面。

而我们自己创建的动态库就在.app目录下的Framework文件夹里。

下图就是测试工程的目录

我这里用了一个测试工程,即有系统的动态库(WebKit),又有自己的动态库(DFCUserInterface),我们可以看一下可执行文件中对动态库的链接地址。用查看可执行文件。其中@rpth这个路径表示的位置可以查看,而现在表示的其实就是.app下的Framework文件夹。

下图表示了静态库,自己创建的动态库和系统动态库:

系统在加载动态库时,会检查 framework 的签名,签名中必须包含 TeamIdentifier 并且 framework 和 host app 的 TeamIdentifier 必须一致。 我们在Debug测试的时候是不会报错的,在打包时如果有动态库,那么就会检查。

如果不一致,否则会报下面的错误:

此外,如果用来打包的证书是 iOS 8 发布之前生成的,则打出的包验证的时候会没有 TeamIdentifier 这一项。这时在加载 framework 的时候会报下面的错误:

可以通过 codesign 命令来验证。

如果证书太旧,输出的结果如下:

注意其中的 TeamIdentifier=not set。

我们在用的的时候生成的动态库也可以用查看到。关于动态库的签名等之前没接触过,可以再去查看一下资料。

系统的.framework是动态库,我们自己建立的.framework一般都是静态库。但是现在你用xcode创建Framework的时候默认是动态库,一般打包成SDK给别人用的话都使用的是静态库,可以修改的为。

Framework是Cocoa/Cocoa Touch程序中使用的一种资源打包方式,可以将代码文件、头文件、资源文件、说明文档等集中在一起,方便开发者使用。一般如果是静态Framework的话,资源打包进Framework是读取不了的。静态Framework和.a文件都是编译进可执行文件里面的。只有动态Framework能在.app下面的Framework文件夹下看到,并读取.framework里的资源文件。

Cocoa/Cocoa Touch开发框架本身提供了大量的Framework,比如Foundation.framework/UIKit.framework/AppKit.framework等。需要注意的是,这些framework无一例外都是动态库。

平时我们用的第三方SDK的framework都是静态库,真正的动态库是上不了AppStore的(iOS8之后能上AppStore,因为有个App Extension,需要动态库支持)。

创建静态Framework

1.选择Framework

创建

2.选择为静态库

3.生成对应版本的静态库

静态库的版本(4种)

这里debug或release是否生成符号表,是否对代码优化等可以在查看。

我们选择Release版本。编译模拟器和真机的所有CPU架构。

然后选择模拟器或者运行编译就会生成对应版本的了。

4.合成包含真机和模拟器的Framework

终端cd到,然后执行以下代码,就会在目录下生成新的包含两种的执行文件,然后复制到任何一个里替换掉旧的就可以了。

或者在工程的里添加以下脚本,真机和模拟器都Build一遍之后就会在工程目录下生成文件夹,里面就是合并之后的Framework。

Framework目录

Framework的资源文件

CocoaPods如何生成Framework的资源文件

我们能看到用cocoapods创建Framework的时候,Framework里面有一个.bundle文件,跟Framework同级目录里也有一个.bundle文件。这两个文件其实是一样的。

那这两个.bundle是怎么来的呢?我们能看到用生成的pod里面,pods这个PROJECT下面会为每一个pod生成一个,比如我有一个pod叫做,那么就会有一个叫的,最后这个target生成的就是。 那么如果这个pod有资源文件的话,就会有一个叫的,最后这个target生成的就是。

上面创建静态Framework例子里生成资源文件

在的的里加入这个这个.bundle,在Framework里面就会生成这样一个bundle。 在的的里加入这个target:,就会在Framework的同级目录里生成这样一个bundle。

静态Framework里不需要加入资源文件

一般如果是静态Framework的话,资源打包进Framework是读取不了的。静态Framework和.a文件都是编译进可执行文件里面的。只有动态Framework能在.app的Framework文件夹下看到,并读取.framework里的资源文件。

你可以用得到.app目录,如果是动态库你能在Framework目录下看到这个动态库以及动态库里面资源文件。然后你只要用得到这个动态库的路径就能读取到里面的资源了。 但是如果是静态库的话,因为编译进了可执行文件里面,你也就没办法读到这个静态库了,你能看到.app下的Framework目录为空。

在framework或子工程中使用xib

问题

跟着 iOS8 / Xcode 6 同时发布的还有 Swift。如果要在项目中使用外部的代码,可选的方式只有两种,一种是把代码拷贝到工程中,另一种是用动态 Framework。使用静态库是不支持的。

造成这个问题的原因主要是 Swift 的运行库没有被包含在 iOS 系统中,而是会打包进 App 中(这也是造成 Swift App 体积大的原因),静态库会导致最终的目标程序中包含重复的运行库(这是苹果)。同时拷贝 Runtime 这种做法也会导致在纯 ObjC 的项目中使用 Swift 库出现问题。苹果声称等到 Swift 的 Runtime 稳定之后会被加入到系统当中,到时候这个限制就会被去除了(参考这个问题的问题描述,也是来自苹果自家文档)。

在纯 ObjC 的项目中,CocoaPods 使用编译静态库 .a 方法将代码集成到项目中。在 Pods 项目中的每个 target 都对应这一个 Pod 的静态库。

当不想发布代码的时候,也可以使用 Framework 发布 Pod,CocoaPods 提供了 选项来使用第三方 Framework。

对于 Swift 项目,CocoaPods 提供了动态 Framework 的支持。通过 选项控制。对于 Swift 写的库来说,想通过 CocoaPods 引入工程,必须加入 选项。

关于 use_frameworks!

在使用的时候在里加入 ,那么你在编译的时候就会默认帮你生成动态库,我们能看到每个源码Pod都会在Pods工程下面生成一个对应的动态库Framework的,我们能在这个的看到默认设置是。也就是会生成一个动态Framework,我们能在下面看到每一个Pod对应生成的动态库。

这些生成的动态库将链接到主项目给主工程使用,但是我们上面说过动态库需要在主工程target的中添加才能使用,而我们并没有在中看到这些动态库。那这是怎么回事呢,其实是已经执行了脚本把这些动态库嵌入到了.app的Framework目录下,相当于在加入了这些动态库。我们能在主工程target的里看到执行的脚本。

所以Pod默认是生成动态库,然后嵌入到.app下面的Framework文件夹里。我们去Pods工程的target里把设置为。那么生成的就是静态库,但是也会把它嵌入到.app的Framework目录下,而因为它是静态库,所以会报错:

Xcode7创建静态库和Framework

到此这篇动态库和静态库有什么区别(静态库和动态库的缺点)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • tp9950倒车影像(t700倒车影像没反应)2025-07-10 10:54:10
  • 手机号经常被发验证码(手机号一直被发验证码怎么报警)2025-07-10 10:54:10
  • 怎么建立dbf文件(怎样新建一个dbf文件)2025-07-10 10:54:10
  • gikj是什么意思(gikh什么意思)2025-07-10 10:54:10
  • max30100中文手册(max3096中文手册)2025-07-10 10:54:10
  • windows的基本操作(windows的基本操作步骤)2025-07-10 10:54:10
  • git上传到指定目录(git上传整个项目)2025-07-10 10:54:10
  • 回环地址有什么用处(回环地址有什么用处吗)2025-07-10 10:54:10
  • 神秘代码网站(免费源代码网站)2025-07-10 10:54:10
  • 回环地址(回环地址的用途)2025-07-10 10:54:10
  • 全屏图片