iOS静态库 【.a 和framework解析4887王中王鉄算盘奖结

来源:http://www.smjxgs.com 作者:操作系统 人气:55 发布时间:2019-08-08
摘要:iOS静态库 【.a 和framework解析】【超详细】,ios.a 最近项目中的登录和支付模块,需要封装成静态库,做下记录及踩的坑。 本文章内容参考网络上搜集到的资料。本人只是整理,已被日

iOS静态库 【.a 和framework解析】【超详细】,ios.a

最近项目中的登录和支付模块,需要封装成静态库,做下记录及踩的坑。

本文章内容参考网络上搜集到的资料。本人只是整理,已被日后查看之用。原文地址:静态库与动态库的区别?

一、什么是库?

库是共享程序代码的方式。

库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。
iOS中的静态库有 .a 和 .framework两种形式;动态库有.dylib 和 .framework 形式,后来.dylib动态库又被苹果替换成.tbd的形式。

库介绍

库是共享程序代码的方式

库从本质上来说是一种可执行代码的二进制格式,可以被载入到内存中执行。库分静态库和动态库两种;iOS中静态库有.a和.framework两种形式;动态库有.dylib和.framework形式,后来.dylib动态库又被苹果替换成.tbd形式。

静态库与动态库的区别:

静态库和动态库是相对于编译期和运行期的,静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为程序运行期间还需要动态库的存在。

同一个静态库在不同程序中使用时,每个程序都要导入一次,打包时也被打包进去,和程序形成一个总的工程文件。而动态库在不同程序中,打包时并没有被打包进去,只是在程序运行使用时,才链接载入(如系统的框架UIKit/Foundation等),所以程序体积会小很多,但是苹果不让使用自己的动态库,否则审核就无法通过(最近看到说项目中可以使用,条件是最低支持iOS8.0以上)。

什么是库?

库是共享程序代码的方式。
库从本质上来说是一种可执行代码的二进制格式,可以被载入到内存中执行。库分为静态库和动态库。
iOS中的静态库有.a和.framework两种形式;动态库有.dylib和.framework形式,后来.dylib动态库又被苹果替换成.tbd的形式。

静态库:连接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
动态库:链接时不复制,程序运行时,由系统动态加载到内存,供程序调用,系统只加载一次,多个程序公用,节省内存。【iOS暂时只允许使用系统动态库】;

静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要改静态库;而动态库在编译时并不会被连接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。
总结:同一个静态库在不同程序中使用时,每一个程序中都得导入一次,打包时也被打包进去,形成一个程序。而动态库在不同程序中,打包时并没有被打包进去,只在程序运行时,才链接载入(如系统的框架UIKit、Foundation等),所以程序体积会小很多,但苹果不让使用自己的动态库,否则审核就无法通过。

二、静态库与动态库的区别?

静态库: 链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。

动态库: 链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。[ios暂时只允许使用系统动态库];

静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。
总结:同一个静态库在不同程序中使用时,每一个程序中都得导入一次,打包时也被打包进去,形成一个程序。而动态库在不同程序中,打包时并没有被打包进去,只在程序运行使用时,才链接载入(如系统的框架如UIKit、Foundation等),所以程序体积会小很多,但是苹果不让使用自己的动态库,否则审核就无法通过。

创建framework静态库

1、新建项目,选择Cocoa Touch Framework;如果是创建.a静态库,则选择Cocoa Touch Static Library

4887王中王鉄算盘奖结果 1

新建项目

区别:.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。 .a .h sourceFile = .framework。.framework其实是对.a文件的封装,建议用.framework.

2、导入需要打包的源文件

4887王中王鉄算盘奖结果 2

导入需要打包的源文件.png

3、修改项目配置

(1)注意info.plist文件中的类型

4887王中王鉄算盘奖结果 3

info.plist文件

(2)设置需要暴露的头文件,将需要暴露的头文件从Project处拖入Public处

Public是你期望公开的,Private下的头文件依然是可以暴露出来的,因此名字可能有些误导。在Project下的头文件才是“私有”的,因此,头文件应该放在Public下,或者在Project下。

4887王中王鉄算盘奖结果 4

header文件设置

也可以使用的方法是:选中.h文件,改变Target Membership面板下的设置。

4887王中王鉄算盘奖结果 5

header文件设置方法二

这里需要注意的是暴露出来的头文件中import的其他类也得添加到public中暴露出来。如果不想将import的类暴露出来,那么在头文件中用@class 然后在对应的.m文件中再import。

建议将暴露的.h文件导入到系统推荐的.h文件中,即建项目时自动生成的文件,此工程中的text.h文件,应该使用#import<>格式导入。

(3)设置编译模式,在Xcode菜单【Product】--->【Scheme】--->【Edit Scheme...】中

4887王中王鉄算盘奖结果 6

设置编译模式

注意:debug:调试版本,系统本身也会有一些调试代码,此版本体积会稍大,运行会稍慢;release:发布版本,系统会去除调试代码,体积变小,运行速度变快,对用户来说没有明显感觉

如果此处不将Build Configuration改为Release,则打包出来的静态库会存于【Debug-iphoneos】和【Debug-iphonesimulator】两个文件夹下。

我们一般都使用Release模式,因为程序最终发布之后是Release版的,所以静态库也是在Release模式下使用。

(4)设置编译出的静态库包含的指令集

4887王中王鉄算盘奖结果 7

设置指令集

模拟器:iPhone4s~5 : i386 iPhone5s~6plus : x86_64

真机:iPhone3gs~4s : armv7 iPhone5~5c : armv7s iPhone5s~6plus : arm64

 armv7s这个架构, 在2014年10月份的xcode版本更新中, 取消了默认导出此架构. 可以不用支持此架构. 如果要支持, 需要手动添加3个架构.

如果这里,设置为YES,那么编译出来的.a静态库就只包含当前设备的指令集。 举个例子:如果我们选择iPhone 5模拟器【Command B】编译,则编译出来的.a静态库只能用iPhone4s5模拟器跑程序,用iPhone5s6plus,则会报找不到x86_64的libFMDB库。 设置为NO,则会把所有指令集的都打包合并。

(5)修改生成的Mach-O格式

4887王中王鉄算盘奖结果 8

设置格式

.framework可以是静态库也可以是动态库,系统的.framework都是动态库,而用户制作的基本上都是静态库,苹果不允许用户在程序中使用自己制作的动态库上线。

(6)其他设置:不设置也不会有太大的影响

特别是那些在二进制库中遗留下的设置,编译器提供给你一个选项,来消除无效代码:永远不会被执行的代码。当然你也可以移除掉一些debug用符号,例如某些函数名称或者其他跟debug相关的细节。

因为你正在创建framework供他人使用,最好禁掉这些功能(无效代码和debug用符号),让用户自己选择对自己的项目有利的部分使用。和之前一样,使用搜索框,改变下述设置:

Dead Code Stripping设置为NO

Link With Standard Libraries 设置为NO

Strip Debug Symbol During Copy 全部设置为NO

Strip Style设置为Non-Global Symbols

4、编译生成静态库

编译时,需要真机(选择Generic ios Device)和模拟器各编译一次,这样Products目录下的text.framework静态库才会变为黑色,右键show in Finder 可以进入Products目录

5、合并模拟器framework的二进制文件和真机framework的二进制文件

4887王中王鉄算盘奖结果 9

需要合并的二进制文件

如果想要通用需要将模拟器使用的静态库与真机使用的静态库合并成一个静态库,可以使用终端命令来实现。

命令格式:lipo -create 模拟器framework的二进制文件路径 真机framework的二进制文件路径 -output 最终二进制文件路径

4887王中王鉄算盘奖结果 10

命令行合并

每次合成文件时都会出现错误信息,控制台总会报错,但仍会生成.lipo文件的二进制文件,在网上看到的一种解决办法就是:将此文件名修改成需要合并的二进制文件的名称。

在用它替换掉之前的二进制文件,此时的.framework便是我们需要的静态库文件

4887王中王鉄算盘奖结果 11

合并后的二进制文件

注意:(1)如果创建的framework中使用了category类,则在使用framework的项目配置中【Other Linker Flags】需要添加参数【-ObjC]或者【-all_load】。

(2)打包的framework使用到一些图片、音频等资源时,需要我们创建一个bundle,命名为ABC.bundle,然后将资源放入bundle中。打包的时候,framework并不包含ABC.bundle。最后在要使用.framework的工程中,新建一个文件夹or group,然后把.framework和ABC.bundle一起拖进去,就可以啦。  

使用:

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"XXXX" ofType:@"bundle"];

NSString *mp3Path = [[NSBundle bundleWithPath:bundlePath] pathForResource:@"Message_system" ofType:@"mp3"];

补充:打包成的静态库肯定是比源码类要大很多的,因为是由不同指令集不同设备的版本合并成的。所以如果你很在意你的app大小,并且也不是很需要打包成静态库的话,还是用原始类吧。 framework静态库中是可以包含图片资源的;而.a静态库中不能包含图片资源,只能另外创建一个目录存放。

参考:

framework为什么既是静态库又是动态库?

系统的.framework是动态库,我们自己建立的.framework是静态库。

三、iOS里静态库形式?

.a和.framework

.a与.framework有什么区别?

.a是一个纯二进制文件, .framework中除了二进制文件之外还有资源文件。
.a文件不能直接使用,至少要有.h文件配合, .framework文件可以直接使用。
.a .h sourceFile = .framework

建议使用.framework

四、iOS里动态库形式?

.dylib和.framework

为什么要使用静态库?

方便共享代码,便于合理使用。
实现iOS程序的模块化。可以吧固定的业务模块化成静态库。
和别人分享你的代码库,但是不想让别人看到你代码的实现,开发第三方SDK的需要。

五、framework为什么既是静态库又是动态库?

系统的.framework是动态库,我们自己建立的.framework是静态库。

制作静态库时的几点注意:

  • 1、注意理解:无论是.a静态库还是.framework静态库,我们需要的都是二进制文件 .h 其他资源文件的形式,不同的是,.a本身就是二进制文件,需要我们自己配上.h和其他文件才能使用,而.framework本身已经包含了.h和其他文件,可以直接使用。

  • 2、图片资源的处理,两种静态库,一般都是把图片文件单独存放在一个.bundle文件中,一般.bundle的名字和.a或.framework的名字相同。.bundle文件很好弄,新建一个文件夹,把它改名为.bundle就可以了,右键,显示包内容就可以向其中添加图片资源。

  • 3、category是我们实际开发项目中经常使用到的,把category打成静态库是没有问题的,但是在这个静态库的工程中,调用category中的方法时会有找不到该方法的运行时错误(selector not recognized),解决办法是:在静态库的工程中配置other linker flags的值为-ObjC。

  • 4、如果一个静态库很复杂,需要暴露的.h比较多的话,就可以在静态库的内部创建一个.h文件(一般这个.h文件的名字和静态库的名字相同),然后把所有需要暴露出来的.h文件都集中放在这个.h文件中,而那些原本需要暴露的.h都不需要再暴露了,只需要把.h暴露出来就可以了。

六、a与.framework有什么区别?

.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。

.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。

.a .h sourceFile = .framework。

建议用.framework.

创建.a静态库

第一步,新建工程。一般使用工程名就使用库的名称,比如我们这里用jingtaiku来创建静态库,我们的工程名就取为jingtaiku,创建的.a静态库就是jingtaiku.a。

4887王中王鉄算盘奖结果 12

创建工程.png

第二步、导入需要打包的资源文件,同时把资源文件需要外界访问的.h文件导入到系统推荐的.h文件中。

第三部、真机,模拟器编译一下。就可以生成.a文件(必须先用真机,要不然,不能生成)。

4887王中王鉄算盘奖结果 13

第四步、Xcode生成的.a文件默认没有导出.h文件。需要自己添加。

第五步、导出你自己的静态库的配置

4887王中王鉄算盘奖结果 14

注意:如果第五步中,不降Build Configuration改为Release,则打包出来的静态库会存于【Debug-iPhoneos】和【Debug-iphonesimulator】两个文件夹下。我们一般都是使用Release模式,因为程序最终会发布之后是Release版的,所以静态库也是在Release模式下使用。

第六步、合成模拟器的架构【默认:模拟器只会生成对应的1种架构】

4887王中王鉄算盘奖结果 15

如果第六步这里,设置为YES,那么编译出来的.a文件库就只包含当前设备的架构。

第七步、合并架构【真机和模拟器】
真机和模拟器合并:

七、为什么要使用静态库?

方便共享代码,便于合理使用。

实现iOS程序的模块化。可以把固定的业务模块化成静态库。

和别人分享你的代码库,但不想让别人看到你代码的实现。

开发第三方sdk的需要。

lipo -create 静态库1.a(路径) 静态库2.a(路径) -output 静态库.a (你最好cd到工程目录下,这样导出的文件在你工程目录下)

第八步、资源包的问题

1、静态库的资源,都应该放到后缀为.bundle的文件夹中-->避免文件与本地文件重名被覆盖,导致加载资源文件出错。【注:要加载bundle路径】
2、静态库打包时,并不会打包资源文件 --> 需要手动拖进去

4887王中王鉄算盘奖结果 16

八、制作静态库时的几点注意:

1注意理解:无论是.a静态库还.framework静态库,我们需要的都是二进制文件 .h 其它资源文件的形式,不同的是,.a本身就是二进制文件,需要我们自己配上.h和其它文件才能使用,而.framework本身已经包含了.h和其它文件,可以直接使用。

2图片资源的处理:两种静态库,一般都是把图片文件单独的放在一个.bundle文件中,一般.bundle的名字和.a或.framework的名字相同。.bundle文件很好弄,新建一个文件夹,把它改名为.bundle就可以了,右键,显示包内容可以向其中添加图片资源。

3category是我们实际开发项目中经常用到的,把category打成静态库是没有问题的,但是在用这个静态库的工程中,调用category中的方法时会有找不到该方法的运行时错误(selector not recognized),解决办法是:在使用静态库的工程中配置other linker flags的值为-ObjC。

4如果一个静态库很复杂,需要暴露的.h比较多的话,就可以在静态库的内部创建一个.h文件(一般这个.h文件的名字和静态库的名字相同),然后把所有需要暴露出来的.h文件都集中放在这个.h文件中,而那些原本需要暴露的.h都不需要再暴露了,只需要把.h暴露出来就可以了。

九、创建.a静态库

第一步,新建工程。一般使用工程名就使用库的名称,比如我这里用LIB来创建静态库,我的工程名就取名为LIB,创建的.a静态库就是LIB.a。

第二步,删除.m文件,保留.h文件, 一般静态库都有一个总的.h文件,方便外部导入头文件。然后导入需要打包的源文件。

第三步,先用真机,编译一次,再用模拟器编译一次。就可以生成.a文件(必须先用真机要不然,不能生成)。

第四步,Xcode生成的.a文件默认没有导出.h文件。需要自己添加。

第五步,导出Products静态库的配置(其实不用设置此步骤,如果真机编译的话,生成导出的时候系统默认会变成Releasse[但是模拟器不会(如果不改这里 得需要把Debug设置为NO)])

注意:如果第五步中,不将Build Configuration改为Release,则打包出来的静态库会存于【Debug-iphoneos】和【Debug-iphonesimulator】两个文件夹下。
我们一般都使用Release模式,因为程序最终发布之后是Release版的,所以静态库也是在Release模式下使用。

第六步,合成模拟器的架构【默认:模拟器编译只会生成对应的1种架构,真机编译会合成两种架构】

如果第六步这里,设置为YES,那么编译出来的.a静态库就只包含当前设备的架构。

举个例子:如果我们选择iPhone 5模拟器【Command B】编译,则编译出来的.a静态库只能用iPhone4s~5模拟器跑程序, 用iPhone5s~6plus,则会报找不到x86_64的libFMDB库。

设置为 NO 之后,【Command B】不管选择哪个【模拟器】,则都会把【386 : 32位架构 4S ~ 5】【x86_64 : 64位架构 5S ~ 现在的机型】的架构都打包合并。

【注】【真机】不设置[Build Active Architecture Only]也默认会自动合并的armv7 和amr64架构 。但是armv7s架构被苹果放弃了,真机要想合并armv7s的话需要进行如下操作再编译。(其实没必要设置这个)

第七步,合并架构【真机和模拟器】

真机和模拟器合并: lipo -create 静态库1.a(路径) 静态库2.a(路径)-output 新静态库.a

第八步,资源包的问题

  1. 静态库的资源, 都应该放到后缀为.bundle的文件夹中 --> 避免文件与本地文件重名被覆盖, 导致加载资源文件出错【注:要加载bundel路径】

  2. 静态库打包时, 并不会打包资源文件 --> 需要手动拖出去

一. 经典报错:

找不到符号在XX架构上

Undefined symbols for architecture x86_64(armv7/armv7s/amr64/i386)

二. 架构的分类

1、模拟器架构: 2种

i386 : 32位架构 4S ~ 5

x86_64 : 64位架构 5S ~现在的机型

2、真机架构: 3种

armv7 : 32位架构 3GS ~ 4S

armv7s: 特殊的架构 5 ~ 5C (此架构有问题, 有的程序变得更快, 有的程序变得更慢)

amr64 : 64位架构 5S ~现在的机型

64位/32位: 内存寻址不同

三. 如何查看静态库架构

找到Products文件夹, 如果.a文件是黑色, 右键打开 到Products文件夹

终端中lipo -info

Generic iOS Device编译出来的OS可用, 有2种架构:armv7/ arm64 (不包含armv7s: 特殊的架构)

iPhone6S模拟器编译出来的: x86_64

iPhone4S模拟器编译出来的: i386

(不设置Build Active Architecture Only的情况下真机编译2种架构, 模拟器编译:对应的1种架构)

四. 合成架构

一般来说, 只需要前两步即可

  1. 模拟器架构的合成: Target --> Build Settings --> Build Active Architecture Only(是否只编译当前架构) --> Debug 改为NO(改为NO, 模拟器就可以直接合成2种架构)

  2. 真机和模拟器合并: lipo -create 静态库1.a 静态库2.a -output 新静态库.a

3.* armv7s这个架构, 在2014年10月份的xcode版本更新中, 取消了默认导出此架构. 可以不用支持此架构.

如果要支持, 需要手动添加3个架构.

五. Debug和Release版本

一般来说, 我们应该发布的是release版本.

debug:调试版本, 系统本身也会有一些调试代码. 此版本体积会稍大, 运行会稍慢

release: 发布版本, 系统会去除调试代码, 体积变小, 运行速度变快. 对用户来说没有明显的感觉

六. 到底要不要合成多个架构

真机和模拟器合成的好处: 调试会非常方便, 缺点是体积会变大(一种架构就占用一部分体积).

真机和模拟器不合成的好处:体积小, 缺点是调试稍显麻烦.

七. 资源包的问题

  1. 静态库的资源, 都应该放到后缀为.bundle的文件夹中 --> 避免文件重名被覆盖, 导致加载资源文件出错

  2. 静态库打包时, 并不会打包资源文件 --> 需要手动拖出去

十、创建framework静态库

第一步、新建工程。一般使用工程名就使用库的名称

第二步、导入需要打包的资源文件,同时把资源文件需要外界访问的.h文件导入到系统推荐的.h中

第三步、真机,模拟器编译一下。可能会需要输入AppleID 。导出的文件没有包含.h

第四步、导出.h

第五步、可以查看一下 没合并模拟器架构之前包含几个同.a(可跳过此步)(真机包含两个,模拟器包含一个)

第六步、合成架构【同.a五六步详细看上边】

第七步,合并架构【真机和模拟器】【注意 合并之后的动态/静态库要与原来的名称一致。不然用的时候编译报错】

第八步、动态库变静态库【默认是动态】好处是将来使用时不需要设置添加动态库(也就是下边的方法)

最后步、

Framework制作后,默认是动态库.使用时,需要设置一下: Tarteg --> General --> Embedded Binaries -->需要添加对应的动态库 【注意 要是制作的时候更改为静态库的话,就不用执行此方法】

【.a 和framework解析】【超详细】,ios.a 一、什么是库? 库是共享程序代码的方式。 库从本质上来说是一种可执行代码的二进制格...

本文由4887王中王鉄算盘奖结果发布于操作系统,转载请注明出处:iOS静态库 【.a 和framework解析4887王中王鉄算盘奖结

关键词:

最火资讯