iOS 静态库和动态库的基本介绍和使用

什么是库 ?

库就是程序代码的集合,将N个文件组织起来,是共享程序代码的一种方式。

库的分类

  • 开源库:源代码是公开的,可以看到每个实现文件(.m文件)的实现,例如GitHub上的常用的开源库:AFNetworking、SDWebImage等;
  • 闭源库:不公开源代码,是经过编译后的二进制文件,看不到具体的实现。闭源库又分为:静态库 和 动态库

静态库存在的形式

  • .a
  • .framework

动态库的存在形式

  • .dylib
  • .framework

静态库和动态库的区别

  • .a文件肯定是静态库,.dylib肯定是动态库,.framework可能是静态库也可能是动态库;
  • 静态库在链接时,会被完整的复制到可执行文件中,如果多个App都使用了同一个静态库,那么每个App都会拷贝一份,缺点是浪费内存。类似于定义一个基本变量,使用该基本变量是是新复制了一份数据,而不是原来定义的;
  • 动态库不会复制,只有一份,程序运行时动态加载到内存中,系统只会加载一次,多个程序共用一份,节约了内存。类似于使用变量的内存地址一样,使用的是同一个变量;
  • 但是项目中如果使用了自己定义的动态库,苹果是不允许上架的,在iOS8.0以后苹果开放了动态加载.dylib的接口,用于挂载.dylib动态库

静态库的运用场景

  • 保护自己的核心代码,如讯飞语言摸索了好多年探索出的结果当然要保护起来了,都公开了公司还怎么生存。
  • 将MRC的项目打包成静态库,可以在ARC下直接使用,不用转换。如别人使用MRC写的开源库,放到自己ARC项目中,需要对每个文件加一个编译参数 -fno-objc-arc,这样相对来说麻烦,将整个工程打包成静态库直接放到项目中即可,也不用对每个文件添加编译选项。

静态库的特点

.a + .h

.a : 可以看做所有.m文件加密后的一个二进制文件
.h : 头文件用户暴漏可用的接口(方法)

制作静态库.a

  1. 新建静态库New—>Project—>Cocoa Touch Static Library
    这里写图片描述
  2. 写一个方法模拟一个功能
    这里写图片描述

这里写图片描述
3. 指定静态库需要公开的头文件
这里写图片描述
4. 选择模拟器iphone6s, 然后 Command + B 编译静态库, 可以看到iFly.a文件名由红色变为黑色,右键 Show In Finder
这里写图片描述
5. 使用静态库,新建一个工程,然后将iFly.a 和 include头文件拖进项目中,然后使用iFly.h公开的方法,然后选择iphone6s 模拟器运行
这里写图片描述

制作静态库相关问题

  1. 我们在制作静态库是使用的模拟器iPhone6s, 如果对测试项目TestStaticLib使用iPhone6s运行完全没问题,但是如果选择模拟器为iphon5和Generic iOS Device进行编译(command + B)就会 报错:Undefined symbols for architecture i386(未定义的符号i386架构)
    这里写图片描述

这里写图片描述

架构是神马东东?

CPU架构是CPU厂商给属于同一系列的CPU产品定的一个规范,主要目的是为了区分不同类型CPU的重要标示。模拟器上的架构和真机上的架构是不一样的,模拟器和模拟器之间,真机和真机之间的架构也是不同的。如果静态库的架构和测试项目对应的模拟器或真机上的架构不对应就会报“未定义的符号XXX架构”, 由此可以得出模拟器上的静态库!

模拟器架构

  • iPhone4s ~ 5 : i386
  • iPhone5s ~ 7Plus : x86_64

真机架构

  • 3GS~4s : armv7
  • 5/5c : armv7s(armv7兼容armv7s)
  • 5s ~ 6sPlus : arm64

使用iPhone6s打包的静态库架构是:x86_64, 测试项目选择的是模拟器iPhone5对应的架构是:i386, 架构不匹配所以报Undefined symbols for architecture i386

查看静态库对应的架构
在终端上使用命令: lipo -info Xxx.a
这里写图片描述

input file libiFly.a is not a fat file:输入文件libiFly.a不是一个胖文件,胖文件是指只支持一个架构,不兼容其它架构。

让静态库支持所有模拟器对应的架构

Build Settings—>Build Active Architecture Only(只构建活跃的架构)—-> NO
什么叫只构建活跃的架构?所谓活跃的架构是指当前选中的模拟器的架构,你选中的就称为活跃的,你没有选中的那些称为不活跃的,重新编译(Command + B)一下静态库,可以拖到测试项目中选中各种模拟器进行测试都是正常的。
这里写图片描述

重新编译之后查看静态库支持的架构,同时支持i386和x86_64,是一个胖文件
这里写图片描述

静态库的版本

静态库有4种版本:

  • 调试版本:不会对代码进行优化
    • 模拟器版本
    • 真机版本
  • 发布版本 :会对代码进行优化,执行效率相对调试版本快,但不会有明显的差别
    • 模拟器版本
    • 真机版本

选中模拟器编译默认是调试版-模拟器版本,选中Generic iOS Device默认是是调试版本-真机版本

生成Release版本的静态库

首先编辑静态库对应的Scheme为Release,然后分别选择模拟器或真机Command + B 进行编译

这里写图片描述

这里写图片描述

合并静态库

我们知道模拟器版本的静态库和真机版的是不能通用的,那么怎样让一个静态库即支持模拟器又支持真机呢?

使用终端 lipo -create Xxx1.a Xxx2.a -output Xxx.a
这里写图片描述
合并后同时支持i386、armv7、x86_64、arm64 这四种架构,合并就是将两个.a文件相加,合并后文件的大小是两个文件之和。通常自己制作静态库给别人用一般是给两个发布版对应的模拟器和真机版本,不给合并版本,因为用户想合并可以自己进行合并,如果给用户一个合并版的,用户则无法分解的。

制作静态库.framework

  1. 创建静态库工程,默认是动态库,修改Build Settings—>Mach-O Type:Static Library
    这里写图片描述
    这里写图片描述
  2. 创建一个类,模拟静态库中的一个功能
    这里写图片描述
  3. 公开头文件
    这里写图片描述
    这里写图片描述
  4. 将其他需要公开的头文件包含到总的头文件中
    这里写图片描述
    iFly.h 是一个总的头文件,可以将其他需要公开的文件都统一写到总的头文件中,用户在使用的时候就导入这一个总的头文件即可
  5. 修改Build Settings–>Build Active Architecture Only: NO, 将Scheme修改为Release 分别选择真机和模拟器进行编译 Command + B, 右键iFly.framework Show In Finder
    这里写图片描述
    这里写图片描述
  6. 查看Release版本的模拟器和真机支持的架构
    这里写图片描述
  7. 创建一个项目进行测试,将Release-iphonesimulator下的iFly.framework拖进到工程中,并调用静态库中的方法
    这里写图片描述

制作动态库.framework

制作动态库和上面步骤差不多,不同的是在编译framework时要指定Mach-O Type: Dynamic Type
这里写图片描述

将.framework文件添加到General—> Embedded Binaries 中,不添加会报错

这里写图片描述

这里写图片描述

.bundle

在使用第三方库时有可能会有一个.bundle文件,.bundle其实是一个物理文件夹,里面可以放图片等资源。因为.bundle是一个物理文件夹,所以当被拖入到项目中就不会和自己项目中的图片重名。

.a 和 .framework

使用.a时需要同时将.a 和 .h 文件拖入到工程中,使用.framework时直接将这个文件夹拖入进去即可,因为.framework文件夹中已经包含了.h文件。

.a + .h + .bundle = .framework, 使用.framework更加方便

静态库如何一边开发一边进行调试

创建一个复合项目
1. 创建一个普通工程Single View Application
2. 在TARGETS中添加一个静态库
这里写图片描述这里写图片描述这里写图片描述

这里写图片描述
3. 在普通Target中添加目标依赖 Target Dependencies,选中刚才的静态库
4. 在普通Target–> Link Binary With Libraries 中添加静态库
这里写图片描述
5. 在ViewController#viewDidLoad中测试
这里写图片描述
这里写图片描述
6. 至此静态库开发好,测试完成后修改静态库对应的Build Active Architecture Only:NO
7. 修改Scheme为Release
8. 暴漏头文件:Build Phases —> Copy Files
9. 分别对Release的真机和模拟器进行Command + B

Swift不支持静态库只支持动态库

Swift is not supported for static libraries.
Swift暴漏方法的方式:Swift不像OC那样有头文件,将Swift中的类和方法用public修饰就可以将类和方法暴漏出来

1 4 收藏 8 评论

关于作者:iOSDevCoder

Java iOS开发 个人主页 · 我的文章 · 1 ·  

相关文章

可能感兴趣的话题



直接登录
最新评论
  • 酷酷的哀殿 iOS 2016/10/23

    静态库的运用场景
    下面的两条和静态库没有关系吧

  • 酷酷的哀殿 iOS 2016/10/23

    静态库没有 h 文件

    Static libraries are collections or archives of object files.

  • 酷酷的哀殿 iOS 2016/10/23

    “使用iPhone6s打包的静态库架构是:x86_64,”换成“使用 iPhone6s 模拟器打包的静态库架构是:x86_64,”比较好

  • 酷酷的哀殿 iOS 2016/10/23

    “armv7兼容armv7s”换成 “armv7s兼容armv7” 比较好

  • 酷酷的哀殿 iOS 2016/10/23

    input file libiFly.a is not a fat file:输入文件libiFly.a不是一个胖文件,胖文件是指只支持一个架构,不兼容其它架构。

     

    input file libiFly.a is not a fat file:输入文件 libiFly.a 不是一个胖文件,胖文件是指支持多个架构的 mach-o 文件

  • 酷酷的哀殿 iOS 2016/10/23

    代码是否优化和静态库没有关系,和模拟器也没有关系。它是由编译选项决定的。

  • 酷酷的哀殿 iOS 2016/10/23

    “如果静态库的架构和测试项目对应的模拟器或真机上的架构不对应就会报“未定义的符号XXX架构”, 由此可以得出模拟器上的静态库!”

    这句有些语句不通。

     

跳到底部
返回顶部