文档章节

xcode 8 /iOS10下静态库和动态库的区别 && framework的制作

Marginx
 Marginx
发布于 2016/11/11 23:42
字数 2460
阅读 747
收藏 5
点赞 0
评论 0

这里输入引用文本本文记录一下,在SDK开发完成后,如何高效率制作framework。

##iOS关于静态库、动态库的一些基本概念和理解误区 ###1. 库 库是源代码经过编译,形成的二进制代码,别人项目中使用我们的库的时候,库在参与编译的时候,直接link就OK了,按照link的方式,可以把库分为静态库动态库 ###2. 静态库 静态库在编译的时候会被直接拷贝一份,复制到目标程序里,这段代码在目标程序里就不会再改变了。

一般以**.a** 和 .framework为文件后缀名

这种做法是牺牲应用“体量”来节省编译时间。 ###3. 动态库 与静态库相反,动态库在编译时并不会被拷贝到目标程序中,目标程序中只会存储指向动态库的引用。等到程序运行时,动态库才会被真正加载进来。

动态库的优点是,不需要拷贝到目标程序中,不会影响目标程序的体积,而且同一份库可以被多个程序使用(因为这个原因,动态库也被称作共享库)。

同时,编译时才载入的特性,也可以让我们随时对库进行替换,而不需要重新编译代码。动态库带来的问题主要是,动态载入会带来一部分性能损失,使用动态库也会使得程序依赖于外部环境。如果环境缺少动态库或者库的版本不正确,就会导致程序无法运行

以**.tbd**(之前叫.dylib) 和** .framework** 为文件后缀名

苹果系统为我们提供了很多动态链接库,我们可以在我们项目工程中查看一下

输入图片说明 输入图片说明 ###4. Framework Framework 是一种打包方式,将库的二进制文件,头文件和有关的资源文件打包到一起,方便管理和分发。

Framework只是一种打包方式,其本身和静态、动态无关!

Cocoa Touch Framework 的实际内容为 Header + 动态链接库 + 资源文件

###5. 对Framework认识的误区 误区①:.framework是动态库,.a是静态库,前面已经讲过,不再赘述

误区②:有人说“自定义的动态库苹果审核不通过”,那我打的framework是不是通不过审核?

任何没有时间前提的结论都是耍流氓!!!

在 **iOS 8 / iOS6之前,**iOS 平台不支持使用动态 Framework,开发者可以使用的 Framework 只有系统的framework,这种限制可能是出于安全的考虑

换一个角度讲,因为 iOS 应用都是运行在沙盒当中,不同的程序之间不能共享代码,同时动态下载代码又是被苹果明令禁止的,没办法发挥出动态库的优势,实际上动态库也就没有存在的必要了

但是,码农总是喜欢折腾的,一方面骨子里面有一种“你不让我做我偏要做的倔强”,另一方面用framework确实比用.a加头文件的方式简单,所以这一时期的开发者用了很多**“奇淫技巧”来制作framework**,这就有了Fake Framework 和 Real Framework的区分

华丽的分割线------

输入图片说明

在 **iOS 8 / iOS6后,iOS平台添加了动态库的支持,同时, Xcode 6 也原生自带了 Framework 支持,注意,前后两个维度的不同是两件事,不要混淆。。。

那么,为什么 iOS 8 要添加动态库的支持?

主要的理由大概就是 Extension 的出现。Extension 和 App 是两个分开的可执行文件,同时需要共享代码,这种情况下动态库的支持就是必不可少的了。但是这种动态 Framework 和系统的 UIKit.Framework 还是有很大区别;还有就是为了支持swift

虽然同样是动态框架,但是和系统 framework 不同,app 中的使用的 Cocoa Touch Framework 在打包和提交 app 时会被放到 app bundle 中(App 和 Extension 的 Bundle 是共享的),运行在沙盒里,而不是系统中。也就是说,不同的 app 就算使用了同样的 framework,但还是会有多份的框架被分别签名,打包和加载,因此苹果又把这种 Framework 称为** Embedded Framework**,也正是代码签名机制,通过AppStore发布的APP是无法通过替换服务端下发framework的方式来进行热更新!

##项目遇到的痛点 项目组本来是使用脚本结合xctool(Facebook的一个开源项目)的方式来打包制作framework,但在升级xcode8之后,xctool在xcode8下出现了bug,而且Facebook并没有在第一时间维护这个项目,一时间一脸懵逼。。。

由于项目时间紧,无奈之下只能采用了一个临时解决方案,就是重新下载一个xcode7版本,让xctool在xcode7环境下打包,但这绝非长久之计!

大概一个月之后,虽然xctool项目更新了对 xcode8 以及 xcode8.1 的支持,但还是决定放弃原有的方案,原因有二,首先,Facebook有着很好的开源精神,但是也是出了名的喜欢撒手不管的角儿,万一哪天停止对这个工具的维护,我怎么办!!!用一种简单、稳定、可靠的解决方案是我们急需的;第二,xctool有很强大的功能,但我们在项目中只用了其中一小块,有点杀鸡用牛刀的意思,项目中很多冗余。 ##解决方案 替代方案就是用xcode提供的aggregate结合脚本来制作framework ##制作过程 ###1. 用workspace管理SDK project 新建一个workspace,命名为TestSDKWorkspace 输入图片说明

现在生成的workspace还是一个空的什么都没有,接着往里面添加我们的静态库project

点击左下角的**+**号

输入图片说明

project类型选择cocoa touch framework,取名为TeskSDK 输入图片说明

在SDK项目中添加测试源代码,写一个Test类,对外提供testMethod方法,注意,这个类要添加到SDK target中去!

#import <Foundation/Foundation.h>
@interface Test : NSObject
- (void)testMethod;
@end

#import "Test.h"
@implementation Test
- (void)testMethod{
    NSLog(@"--------");
    NSLog(@"this is a test method");
    NSLog(@"--------");
}
@end

我们决定对外暴露Test.h,将其添加至接口文件中

输入图片说明

此时,我们编码准备工作已经做好了,command+B,我们可以在product文件夹下面看到有一个TestSDK.framework从红变黑,这是不是意味着我们需要的framework已经大功告成了呢?

no!!!我们此时只是在特定平台下编译的,得到的也只是这个平台下的framework,我们在文件夹中查看如下图

输入图片说明

这就意味着我们要打同平台的包,需要经过多次编译,最后再去合成,这太麻烦了 ###2. 用“Aggregate+脚本”制作framework 选择TARGETS点击然后添加Aggregate

输入图片说明

添加如下脚本到Aggregate target对应的build phases-->run script中

#!/bin/sh
#要build的target名
TARGET_NAME=${PROJECT_NAME}
if [[ $1 ]]
then
TARGET_NAME=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}_Products/"

#创建输出目录,并删除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
rm -rf "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework"

#分别编译模拟器和真机的Framework
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build

#拷贝framework到univer目录
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_FOLDER}"

#合并framework,输出最终的framework到build目录
lipo -create -output "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"

#删除编译之后生成的无关的配置文件
dir_path="${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/"
for file in ls $dir_path
do
if [[ ${file} =~ ".xcconfig" ]]
then
rm -f "${dir_path}/${file}"
fi
done
#判断build文件夹是否存在,存在则删除
if [ -d "${SRCROOT}/build" ]
then
rm -rf "${SRCROOT}/build"
fi
rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"
#打开合并后的文件夹
open "${UNIVERSAL_OUTPUT_FOLDER}"

输入图片说明 ###3. 生成framework 在target中选择TestAggregate,build device选择Generic Device,然后 command + B 输入图片说明

由于脚本末尾添加了open命令,编译结束之后会打开framework所在的文件夹

至此,SDK生成完毕,我们需要写个demo工程验证一把 ###4. 验证framework 在workspace中新建一个demo工程,然后把TestSDK.framework引入

输入图片说明

在viewController中调用SDK方法

输入图片说明

从控制台的输出可以看出,我们已经成功的调起TestSDK中的方法。

我的另外一篇文章解决引用百度地图sdk冲突问题,其中介绍了如何查看framework的内部结构,你可以用里面的方法来查看我们打出来的framework是否是通平台的包 ##总结

  1. 开发是一个不断踩坑和填坑的过程,制作framework在iOS开发中是一个比较小众的需求,我会持续的把我遇到的蛋疼的事儿记录下来,以供来着参考,有更好的方法也欢迎讨论
  2. 在SDK制作过程中用workspace的方法管理project是一个很有效率的方法,这是我们团队的adams总结使用的,通过这种方法可以源码project和demo project放在一起,可以同时在一个地方搞定两件事:SDK开发和framework集成
  3. 学会制作framework仅仅是万里长征第一步,framework给到第三方集成过程中会遇到各种麻烦,这就需要不断的总结和沉淀
  4. 本文目前为止制作的是动态的framework,如果你的需求是做一个静态的framework,变化很简单,你只需要改变building settings -- > Mach-o type为static即可
  5. 默认的iOS develop target是当前最新版本的,你的framework需要兼容低版本的话就需要在build settings --> development --> iOS develop target中设置你的目标版本

© 著作权归作者所有

共有 人打赏支持
Marginx
粉丝 4
博文 17
码字总数 19301
作品 0
深圳
Xcode制作动态及静态Framework

有没有写SDK或者要将一些常用的工具类做成Framework的经历? 你或许自己写脚本完成了这项工作,相信也有很多的人使用 iOS-Universal-Framework ,随着Xcode 6的发布,相信小伙伴们已经都知道了...

余成海 ⋅ 2015/10/28 ⋅ 0

iOS中制作可复用的框架Framework

iOS中制作可复用的框架Framework 在iOS开发中,我们时常会使用一些我们封装好的管理类,框架类,方法类等,我们在实现这些文件时,可能还会依赖一些第三方库或者系统库。如果每次我们复用这些...

行走中的菜鸟 ⋅ 2015/08/17 ⋅ 0

iOS - 静态库、动态库、Framework

背景: 在项目中使用OC和Swift混编, 用Cocoapods导入SwiftyJSON时需要在PodFile里面使用useframeworks!才能安装, 导入成功后编译项目报.h 未能发现的错误. 经过一顿google之后得知如果在cocoa...

Sunxb ⋅ 2016/12/23 ⋅ 0

iOS - Library 库

1、动态库 & 静态库 什么是库: 库是程序代码的集合,是共享程序代码的一种方式。根据源代码的公开情况,库可以分为 2 种类型: 开源库: 闭源库: 静态库和动态库: iOS 中静态库和动态库的...

仟0123 ⋅ 2016/09/05 ⋅ 0

iOS 深入理解framework

//联系人:石虎 QQ:1224614774 昵称:嗡嘛呢叭咪 一、概念 1.framework(框架,其实相当于静态框架,不是动态库) 2.打包framework还是一个比较重要的功能,可以用来做一下事情: (1)封装功能...

石虎132 ⋅ 01/08 ⋅ 0

iOS中制作可复用的框架Framework

iOS中制作可复用的框架Framework 在iOS开发中,我们时常会使用一些我们封装好的管理类,框架类,方法类等,我们在实现这些文件时,可能还会依赖一些第三方库或者系统库。如果每次我们复用这些...

珲少 ⋅ 2015/08/12 ⋅ 0

iOS中的静态库与动态库,区别、制作和使用

如果我们有些功能要给别人用,但是又不想公开代码实现,比如高德地图、第三方登录分享等等,这时候我们就要打包成库了。库分静态库和动态库两种: 静态库:以 和 为文件后缀名。 动态库:以(...

秦无炎 ⋅ 2016/12/01 ⋅ 0

Xcode7制作动态及静态Framework

iOS中的静态库和动态库 概念 静态库(Static Library)以 .a 为后缀,它是你的源码的实现.m文件编译而成的二进制文件集合,需要配合上暴漏的.h文件使用,它在引用链接时拷贝至可执行文件中,程序运...

朝雨晚风 ⋅ 2016/07/19 ⋅ 0

Framework打包前传

关于库的一些基础知识 首先来了解一下什么是库:库(Library)其实是一段编译好的二进制代码,然后将头文件暴露出来(OC中就是.h文件,swift中打包后Xcode将会自动生成.h文件 需要将Swift代码前...

樗同学 ⋅ 2016/09/27 ⋅ 0

iOS静态库 【.a 和framework】【超详细】

一、什么是库? 库是共享程序代码的方式。 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。 iOS中的静态库有 .a 和 .framework两种形式;动态...

卡奇匠 ⋅ 2016/03/30 ⋅ 3

没有更多内容

加载失败,请刷新页面

加载更多

下一页

645. Set Mismatch - LeetCode

Question 645. Set Mismatch Solution 思路: 遍历每个数字,然后将其应该出现的位置上的数字变为其相反数,这样如果我们再变为其相反数之前已经成负数了,说明该数字是重复数,将其将入结果r...

yysue ⋅ 19分钟前 ⋅ 0

Confluence 6 从生产环境中恢复一个测试实例

请参考 Restoring a Test Instance from Production 页面中的内容获得更多完整的说明。 很多 Confluence 的管理员将会使用生产实例运行完整数据和服务的 Confluence 服务器,同时还会设置一个...

honeymose ⋅ 24分钟前 ⋅ 0

Python这么强?红包杀手、消息撤回也可以无视,手机App辅助!

论述 标题也许有点不好理解,其实就是一款利用Python实现的可以监控微信APP内的红包与消息撤回的助手。不得不说,这确实是一款大家钟意的神器。 消息撤回是一件很让人恶心的事,毕竟人都是有...

Python燕大侠 ⋅ 35分钟前 ⋅ 0

压缩打包介绍、gzip压缩工具、bzip2压缩工具、xz压缩工具

压缩打包介绍 压缩的好处不仅能节省磁盘空间而且在传输的时候节省传输时间和网络带宽 windows系统下文件带有 .rar .zip .7z 后缀的就是压缩文件 linux系统下则是 .zip, .gz, .bz2, .xz, ...

黄昏残影 ⋅ 40分钟前 ⋅ 0

观察者模式

1.利用java原生类进行操作 package observer;import java.util.Observable;import java.util.Observer;/** * @author shadow * @Date 2016年8月12日下午7:29:31 * @Fun 观察目标 **/......

Cobbage ⋅ 42分钟前 ⋅ 0

Ubuntu打印服务器配置

参考:https://blog.csdn.net/gsls200808/article/details/50950586 https://blog.csdn.net/jiay2/article/details/80252369 https://wiki.gentoo.org/wiki/HPLIP 由于媳妇儿要大量打印资料,......

大熊猫 ⋅ 48分钟前 ⋅ 0

面试的角度诠释Java工程师(二)

原文出处: locality 续言: 相信每一位简书的作者,都会有我这样的思考:怎么写好一篇文章?或者怎么写好一篇技术类的文章?我就先说说我的感悟吧,写文章其实和写程序是一样的。为什么我会...

颖伙虫 ⋅ 51分钟前 ⋅ 0

github中SSH的Key

https://help.github.com/articles/connecting-to-github-with-ssh/ https://help.github.com/articles/testing-your-ssh-connection/ https://help.github.com/articles/adding-a-new-ssh-k......

whoisliang ⋅ 52分钟前 ⋅ 0

only_full_group_by

我的mysql是在CentOS7.1下面的5.7.17 在 /etc/my.cnf 文件里加上如下: sql_mode='NO_ENGINE_SUBSTITUTION' 然后,重启Mysql服务 systemctl restart mysqld...

SunHacker ⋅ 今天 ⋅ 0

实际项目(SpringBoot项目)中集成Druid

参考网页 https://blog.csdn.net/liuchuanhong1/article/details/55050131 https://blog.csdn.net/CoffeeAndIce/article/details/78707819 https://www.pocketdigi.com/20170530/1577.html 为......

karma123 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部