系列:iOS开发-framework的制作与使用

系列:iOS开发-framework的制作与使用

作为一个iOS开发人员,无论是出于工作需要,还是出于保密需要...
我们都有可能或多或少的想要将一部分源码封装成静态或者动态库,以达到保密或者版权的效果
比如公司想要整理框架作为知识产权等销售,比如你做一个兼职工作,客户想要项目源码,涉及隐私你想要保护起来,比如你想要分享给一个同时一项功能,但是不想给源码...

网上关于Framework制作的教程数不胜数,但是大多都是比较老旧的,所以我把这几天自己制作framework的过程记录下来,并且使用的是最新的Xcode8环境。

前段日子我接了一份兼职,项目做完,完整上线,客户想要源码,出于保密,我想要把一部分主要的核心代码封装起来.
这个兼职本身并不复杂,也就几个页面,核心部分是一个蓝牙的封装和通讯部分


这里写图片描述

核心文件也就是这个蓝牙的实现,其他的话想对来说就是一些界面和自定义的一些简单控件,非核心,我打算封装一个framework来替换这部分代码

步骤:
于是我使用Xcode8创建.


这里写图片描述

选择Cocoa Touch Framework->Next
起一个略屌的名字并创建


这里写图片描述

把几个文件添加进入项目
这里写图片描述

接下来就是设置一些参数了

修改项目最低支持版本


这里写图片描述

修改项目是否支持bitcode
这里写图片描述

这个很多人封装都不一定会想起来并且设置,虽然没有大的影响,但是我觉得我还是保险起见.
接下来.
这里写图片描述

这里解释一下
1.首先是Dead Code Stripping设置为NO,网上对此项的解释如下,大致意思是如果开启此项就会对代码中的”dead”、”unreachable”的代码过滤,不过这个开关是否关闭,似乎没有多大影响,你可以选择忽视不设置
2.然后将Link With Standard Libraries关闭,关闭连接标准库,为了避免重复链接,当然这里还是可以忽视不设置
3.最后将Mach-O Type设为Static Library,framework可以是动态库也可以是静态库,对于系统的framework是动态库,而用户制作的framework只能是静态库。后面我会讲他们之间的区别

再继续设置
然后将需要公开的头文件从Project中拖入Public,至于是否需要将私有的头文件拖入Private,我觉得直接放在Project中即可,若是Private中有头文件,打包以后的framework中会多出一个Private的文件夹包含着放入Private的头文件,不过我觉得如果是私有最好还是不要让别人看到。


这里写图片描述

然后为了方便用户使用,修改XLXBLEManager.h的内容


这里写图片描述

这样初步的环境都配置好了
接下来我们就要封包了,封包的话我们需要考虑该库是否需要支持真机和模拟器同时进行?32位还是64位?debug还是release?
OK,这里是我的设置

我想要封装的是release的库
原因是
Release是发行版本,比Debug版本有一些优化,文件比Debug文件小 Debug是调试版本,Debug和Release调用两个不同的底层库。 1、"Debug是调试版本,包括的程序信息更多" 2、只有DEBUG版的程序才能设置断点、单步执行、使用TRACE/ASSERT等调试输出.3、我封装成库了,还需要断点?单步执行?...


这里写图片描述

选择release
这里写图片描述

接下来是支持的版本
Xcode默认不支持armv7s 我们可以添加上,当然也可以忽略
这里写图片描述

这里写图片描述

这里我更改了Build Active Architecture Only设置我NO,
如果选项设为YES,其编译时模拟器版本只会生成当前模拟器机器的框架,将其设置为NO后,发现用模拟器编译后生成的framework同时包含x86_64和i386架构。
当然这里有几点要说明,其默认的是DEBUG为YES,RELEASE为NO ,我刚刚修改了Scheme为release版本,所以这里其实默认就是NO,我还是可以不用设置

如果我没有修改Scheme,仍然是默认的debug,那么其就是默认的YES,那么结果是我们选择iphone5s及以上的模拟器,其框架为x86_64 iPhone5s以下的模拟器,其框架为i386,那样的话封装的库只能使用相对应的模拟器,否则就会崩溃报错,
为了避免这个问题,我选择NO,让其都支持,无论是debug还是release

OK,所有的准备工作基本全部做完
接下来是编译build
首先选择

这里写图片描述

我们用commond+B build一下->success

然后再随便选择一个模拟器,使用相同的方式再build一下->success

这样其实两个framework就生成了
在什么地方呢?


这里写图片描述

我们能够看到两个文件夹里面分别有一个framework


这里写图片描述

上面的是release版本的真机框架,下面的是release版本的模拟器框架,如果你选择的scheme是debug的话,则这两个文件夹是以debug开头,
这两个framework就是我想要的静态库,我们可以直接添加到想要的项目中使用,当然,我们会想要把两个库合并,让其能够在真机和模拟器同时运行
接下来就会用到终端命令行

打开终端,输入

lipo -create
然后把两个framework里面的XLXBLEManager分别拖到终端来


这里写图片描述

再后面再接着输入
-output ~/Desktop/framework/XLXBLEManager

完整的命令是这样的


这里写图片描述

表示的意思是,合并资源 a b 到指定文件夹 命名为 c 这里~/Desktop/framework/表示桌面的framwork的一个文件夹,你可以自定义

运行,我们在桌面的framework文件夹中发现了合并之后的文件


这里写图片描述

我们看一下其支持的版本

lipo -info XXX

这里写图片描述

各种版本都是支持的,是我想要的库,
我们进入刚才的Release-iphoneos文件夹复制一个XLXBLEManager.framework到桌面来


这里写图片描述

使用合成的XLXBLEManager替换掉XLXBLEManager.framework中的XLXBLEManager

这样,一个合成之后的完整的.framework就结束了


这里写图片描述

接下来是使用framework


这里写图片描述

这里写图片描述

这里写图片描述

在search path 中添加framework的Headers
将之前的代码引用更换成新的库的引用


这里写图片描述

运行!
这里写图片描述

这里封装的是静态的framework,那么动态framework有什么区别呢?

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

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

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

这里是我封装静态库的原因,
如果使用仍然想要使用动态库的话,那么在使用库的时候


这里写图片描述

还要选择在Embedded Binaries中添加相应的库

此外
在项目中引入静态库后,archive的时候如果出现bitcode错误
bitcode bundle could not be generated because ... was built without full bitcode.All object files and libraries for bitcode must be generated from Xcode Archive or Install build for architecture arm64

所以需要打开库工程的此选项并加上-fembed-bitcode参数,重新编译


这里写图片描述

如此archive时就不会出问题了,到此我在制作使用framework时遇到的问题都在这里了。
此外,还有引用框架编译的时候没有报错,在运行的时候报错了,是由于链接发生错误
在使用项目的tagert中的Other Linker Flags 中加入所需的参数,一般是这三个:-ObjC、-all_load、-force_load,尝试添加了第一个应该就能解决问题了


这里写图片描述

至此,制作framework的教程就基本结束了
但是上面的教程是否有点复杂了?
主要的点就在于制作framwork和合并framework上面,有没有办法能够傻瓜式,一键合成需要的静态库或者动态库呢?肯定有的

在选择好最低版本,bitcode设置成NO,Build Active Architecture Only设置我NO,将Mach-O Type设为Static Library之后,我们换一种方式


这里写图片描述

创建一个target
之后选择target


这里写图片描述

添加这段脚本
# Sets the target folders and the final framework product.
# 如果工程名称和Framework的Target名称不一样的话,要自定义FMKNAME
# 例如: FMK_NAME = "MyFramework"
FMK_NAME=${PROJECT_NAME}
# Install dir will be the final output to the framework.
# The following line create it in the root folder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build
# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
open "${INSTALL_DIR}"
这里写图片描述

选择target之后运行


这里写图片描述

你会发现结果是直接在打包项目中添加了一个product文件夹并生成了需要的framework文件!


这里写图片描述

这个就是我们需要的framework文件,并且是合并之后的文件.
我们可以测试看看

这里写图片描述

省去了所有的build->合并->替换的手动过程
直接生成需要的framework文件,至于后面怎么使用framework文件,跟上面一样了...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容