作者:Haley_Wong

最近因为项目中的聊天SDK,需要封装成静态库,所以实践了一下创建静态库的步骤,做下记录。

库介绍

库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。

iOS中的静态库有 .a 和 .framework两种形式;动态库有.dylib 和 .framework 形式,后来.dylib动态库又被苹果替换成.tbd的形式。

静态库与动态库的区别

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

总结:同一个静态库在不同程序中使用时,每一个程序中都得导入一次,打包时也被打包进去,形成一个程序。而动态库在不同程序中,打包时并没有被打包进去,只在程序运行使用时,才链接载入(如系统的框架如UIKit、Foundation等),所以程序体积会小很多,但是苹果不让使用自己的动态库,否则审核就无法通过。

创建.a静态库

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

第二步,删除系统默认创建的【FMDB.h】和【FMDB.m】文件,导入需要打包的源文件。

第三步(方式一),修改项目配置

点击上图中的【3】,弹出的列表中选择【New Headers Phase】,打开【Headers (0 items)】,点击左下角的【+】,选择所有的.h文件。

第三步(方式二),修改项目配置

第四步,修改导出product配置

第五步,修改编译指令集

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

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

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

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

设置为NO,则会把所有指令集的都打包合并。

第六步,编译(快捷键【Command+B】

编译时,需要用模拟器和真机各编译一次,这样Products目录下的libFMDB.a静态库才会变为黑色,右键show in Finder,可以进入Products目录下。

为什么需要用模拟器和真机各编译一次呢?

可以看到Products目录下有【Release-iphoneos】和【Release-iphonesimulator】两个文件件。前者里面是真机使用的.a静态库,后者是模拟器使用的.a静态库。

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

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

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

lipo -create 第一个.a文件的绝对路径 第二个.a文件的绝对路径 -output 最终的.a文件路径。

本文中使用的命令如下:

lipo -create /Users/harvey/Library/Developer/Xcode/DerivedData/FMDB-ctegiztcjikewoeprxxtmryzetfa/Build/Products/Release-iphoneos/libFMDB.a /Users/harvey/Library/Developer/Xcode/DerivedData/FMDB-ctegiztcjikewoeprxxtmryzetfa/Build/Products/Release-iphonesimulator/libFMDB.a -output /Users/harvey/Desktop/libFMDB.a

补充:经过多次实践,第三步的操作省略,依然可以导出可正常使用的包。

如果静态库中有category类,则在使用静态库的项目配置中【Other Linker Flags】需要添加参数【-ObjC]或者【-all_load】。

创建framework静态库

第一步,新建项目

第二步,删除系统默认创建的【FMDB.h】和【FMDB.m】文件,导入需要打包的源文件。

第三步,修改项目配置

首先,设置需要暴漏的头文件

这里需要注意的是暴露出来的头文件中import的其他类也得添加到public中暴露出来。

如果不想将import的类暴露出来,那么在头文件中用@class 然后在对应的.m文件中再import。

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

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

最后修改生成的Mach-O格式

第四步,编译生成静态库

编译时,需要用模拟器和真机各编译一次,这样Products目录下的libFMDB.a静态库才会变为黑色,右键show in Finder,可以进入Products目录下。

第五步,合并模拟器版framework和真机版framework

合并的命令同上面相似,不同之处是:framework静态库合并的不是framework,而是framework下的一个二进制文件,即上一步图中标记的文件。

lipo -create 第一个framework下二进制文件的绝对路径 第二个framework下二进制文件的绝对路径 -output 最终的二进制文件路径。

本文中使用的命令如下:

1
lipo -create /Users/harvey/Library/Developer/Xcode/DerivedData/FMDB-clvayfrjgytqrbdkyqrtcjkxfeuz/Build/Products/Release-iphonesimulator/FMDB.framework/FMDB /Users/harvey/Library/Developer/Xcode/DerivedData/FMDB-clvayfrjgytqrbdkyqrtcjkxfeuz/Build/Products/Release-iphoneos/Release-iphoneos.framework/FMDB -output /Users/harvey/Desktop/FMDB

最后将任何一个framework中的二进制文件替换成合并后的二进制文件即可。

把framework添加到要使用的项目中即可使用。

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

如果使用framework的使用出现【Umbrella header for module 'XXXX' does not include header 'XXXXX.h'】,是因为错把xxxxx.h拖到了public中。

如果出现【dyld: Library not loaded:XXXXXX】,是因为打包的framework版本太高。比如打包framework时,选择的是iOS 9.0,而实际的工程环境是iOS 8开始的。

如果创建的framework类中使用了.dylib或者.tbd,首先需要在实际项目中导入.dylib或者.tbd动态库,然后需要设置【Allow Non-modular Includes ....】为YES,否则会报错"Include of non-modular header inside framework module"。

补充:打包成的静态库肯定是比源码类要大很多的,因为是由不同指令集不同设备的版本合并成的。所以如果你很在意你的app大小,并且也不是很需要打包成静态库的话,还是用原始类吧。

framework静态库中是可以包含图片资源的;而.a静态库中不能包含图片资源,只能另外创建一个目录存放。

填坑记录

上面的注意里提到了一些坑,以及解决办法。这里再记录一些:

1.framework中用到了NSClassFromString,但是转换出来的class 一直为nil。

先来看一下这个API的官方描述

什么意思呢?如果转换出来的class为nil,有两种情况:一种情况是这个类不存在;第二种情况是这个类还没有被load。所以一般出现问题,都是第二种情况。

怎么解决这个问题呢?在主工程的【Other Linker Flags】需要添加参数【-ObjC]即可。

Have Fun!

经验分享:Xcode 创建.a和framework静态库【转】的更多相关文章

  1. 经验分享:Xcode 创建.a和framework静态库

    最近因为项目中的聊天SDK,需要封装成静态库,所以实践了一下创建静态库的步骤,做下记录. 库介绍 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种. iOS中的 ...

  2. Xcode 创建.a和framework静态库(转载)

    库介绍 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种. iOS中的静态库有 .a 和 .framework两种形式:动态库有.dylib 和 .framew ...

  3. Xcode 创建.a和framework静态库

    库介绍 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种. iOS中的静态库有 .a 和 .framework两种形式:动态库有.dylib 和 .framew ...

  4. Xcode 创建.a和framework静态库(转)

    最近因为项目中的聊天SDK,需要封装成静态库,所以实践了一下创建静态库的步骤,做下记录. 库介绍 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种.iOS中的静 ...

  5. iOS 中 .a 和 .framework 静态库的创建与 .bundle 资源包的使用

    iOS 中 .a 和 .framework 静态库的创建与 .bundle 资源包的使用 前言 开发中经常使用三方库去实现某特定功能,而这些三方库通常又分为开源库和闭源库.开源库可以直接拿到源码,和自 ...

  6. iOS:Xcode7下创建 .a静态库 和 .framework静态库

    Xcode7 中创建静态库:.a 和 .framework 一.简单介绍 1.什么是库? 库是程序代码的集合,是共享程序代码的一种方式 2.库的分类 根据源代码的公开情况,库可以分为2种类型 (1)开 ...

  7. Xcode6.1标准Framework静态库制作方法。工程转Framework,静态库加xib和图片。完美解决方案。

    http://www.cocoachina.com/bbs/read.php?tid-282490.html Xcode6.1标准Framework静态库制作方法.工程转Framework,静态库加x ...

  8. iOS SDK开发之 .framework静态库

    查看.a静态库的生成及使用单击此处 注:这篇教程将只使用一小部分Objective-C代码,本文主要讲解从开始到应用的详细步骤.环境:xcode 9.2下面我们开始操作: 第一步:创建一个静态库工程 ...

  9. iOS开发中静态库之".framework静态库"的制作及使用篇

    iOS开发中静态库之".framework静态库"的制作及使用篇 .framework静态库支持OC和swift .a静态库如何制作可参照上一篇: iOS开发中静态库之" ...

随机推荐

  1. jQuery入门第一天

    使用jQuery之前,我们需要加一些代码到HTML文件中. 首先在页面顶端增加一行script元素,然后写上结束符. 浏览器会运行script 里所有的Javascript,包括jQuery. 在你的 ...

  2. uva 1339

    Ancient Roman empire had a strong government system with various departments, including a secret ser ...

  3. mobile web HTML5 app曾经的踩过坑(转)

    兼容性一直是前端工程师心中永远的痛.手机浏览器,因为基本是webkit(blink)内核当道,很多公司,不用考虑IE系的浏览器,所以感觉兼容性上的问题可能会少一些. 但是手机端,虽然出了很多工具,但是 ...

  4. 【BZOJ】3757: 苹果树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3757 题意:n个节点的树,每个点有一种颜色.现有m种询问,每次询问x y a b表示x到y的路径上颜 ...

  5. HDU 4454 Stealing a Cake(枚举角度)

    题目链接 去年杭州现场赛的神题..枚举角度..精度也不用注意.. #include <iostream> #include <cstdio> #include <cstr ...

  6. URAL 1203. Scientific Conference(瞎搞)

    题目链接 本来觉得这不是经典的贪心吗..果断水一次,wa了,看了看discuss,发现貌似不好水,土土的DP了一下,复杂度很高了,又T了...然后想想单调队列,二分什么的...不好往上加,直接搞了标记 ...

  7. Flex Vector使用(转)

    从前(Flex SDK 4.0 以前版本)创建 Vector 实例一定要如下所示,这样的语法使我们在构造 Vector 对象时无法指定元素: var v:Vector.<T> = new ...

  8. 设备像素比devicePixelRatio简单介绍

    本文所说devicePixelRatio其实指的是window.devicePixelRatio, 被所有WebKit浏览器以及Opera所支持,随着显示器的发展,这个属性也慢慢登上了前端技术的舞台. ...

  9. HTTPS原理介绍

    内容来源于:http://www.guokr.com/post/114121/ 自己做个备忘. 二.HTTPS到底安全吗? 这个答案是肯定的,很安全.谷歌公司已经行动起来要大力推广HTTPS的使用,在 ...

  10. Daily Scrum 10.27

    今天是星期天,但大家都没有放松,还是抽出了一定的时间来完成任务.可以感觉出来在编译作业的压力下大家的热情不是很高涨,希望大家坚持下去. 下面是今天的Task统计: 下面是所有迭代的状态: