iOS Framework制作方法

首先静态库和动态库都是以二进制提供代码复用的代码库
静态库 常见的是 .a
动态库常见的是 .dll(windows),.dylib(mac),so(linux)
framework(in Apple): Framework 是Cocoa/Cocoa Touch程序中使用的一种资源打包方式,可以将代码文件、头文件、资源文件、说明文档等集中在一起,方便开发者使用。也就是说我们的 framework其实是资源打包的方式,和静态库动态库的本质是没有关系的

静态库和动态库的区别
静态库: 链接时会被完整的复制到可执行文件中,所以如果两个程序都用了某个静态库,那么每个二进制可执行文件里面其实都含有这份静态库的代码
动态库: 链接时不复制,在程序启动后用dyld加载,然后再决议符号,所以理论上动态库只用存在一份,好多个程序都可以动态链接到这个动态库上面,达到了节省内存(不是磁盘是内存中只有一份动态库),还有另外一个好处,由于动态库并不绑定到可执行程序上,所以我们想升级这个动态库就很容易,windows和linux上面一般插件和模块机制都是这样实现的。

使用静态库的好处:
1.模块化,分工合作
2.避免少量改动经常导致大量的重复编译连接
3.也可以重用,注意不是共享使用

使用动态库的好处:
1.使用动态库,可以将最终可执行文件体积缩小
2.使用动态库,多个应用程序共享内存中得同一份库文件,节省资源
3.使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的。


日常的开发中,我们经常会遇到这样的开发需求。比如 不能提供源码,暴露部分接口出去、 项目功能组件模块化等。这个时候,我们一般就想到了sdk开发。在OC的开发中,我们涉及到的一般是静态库(.a)或者动态库(.framework)。(注:不是所有的.framework就一定是动态库)

一、什么是库?

库是共享程序代码的方式,一般分为静态库和动态库。

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

静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。
注意:动态库只能苹果使用,如果项目中使用了动态库不允许上架(如:jspatch)

三、iOS里静态库形式?

.a和.framework

四、iOS里动态库形式?

.dylib和.framework
(iOS9 取消了.dylib,使用.tbd代替)

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

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

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

.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。
.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。
.a + .h + sourceFile = .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暴露出来就可以了。

开发SDK是选择动态库还是静态库呢?

  • 静态SDK不能嵌套。见iOS中Framework Library嵌套使用。因此,当SDK需要引用其他SDK,且不希望暴露给用户时,只能采用动态库的开发方式。
  • 静态库开发需要编写spec文件,且需要告诉客户如何导入,若嫌其麻烦时可采用动态库开发。
  • 动态库上架需要删除其X86,i386模拟器架构,若嫌其麻烦可采用静态库开发。
  • 若SDK和项目中用到相同的三方库(如:AFNetworking)。
    动态库:工程和项目中可以存在2份AFNetworking,因此开发方便。
    静态库只会存在一份,因此开发相对复杂,但减少了代码的冗余。若嫌2份代码重复占存储资源时,可采用静态库开发。
  • 静态方式开发,一直是iOS SDK开发的主流方式。百度地图、高德地图等大型三方SDK均是采用静态的方式开发。也有采用动态的方式开发SDK的如:环信。
  • 如果SDK和主工程用到了同样的三方库,也有另一种做法。就是把SDK中三方库的类名全改了,只用改类名就可以了,当然一些全局变量也是要改的。用xcodeRename功能,改起还挺快的,真心不麻烦,具体怎么用,百度吧~

制作静态Framework,目前有3种方法:
方法1:通过.a转静态.framework
方法2:通过.bundle转静态.framework
方法3:通过动态.framework转静态.framework
具体见iOS静态Framework制作方法

一,创建iOS的SDK有两种方式
1,以.a的方式.
2,以.framework的方式.
二,这里建议创建以.framework的方式
.framework的格式创建,能为后期避免很多不必要的麻烦.
.framework的格式其实一个文件包,具体的谈不上是一个SDK的库.
.framework包可以是静态,也可以是动态库.
.a是静态的库.

开发工具

对于iOS来说,就是个Xcode,但是考虑成工程搭建和打包的方便建议使用cocoapods和cocoapods-packager。

搭建开发工程:
pod lib create xxx
打包:
pod package xxx.spec

创建时需要选择此处

iOS Framework制作方法_第1张图片
image

修改生成的 Mach-O格式,因为动态库也可以是以 Framework形式存在,所以需要设置,否则默认打出来的是动态库。将 target->BuildSetting->Mach-o Type设为 Static Library(默认为 Dynamic Library)
iOS Framework制作方法_第2张图片
image

关于底下这些参数我们可以使用默认的
iOS Framework制作方法_第3张图片
image

配置Xcode

  • TARGETS -Build Settings - Build Active Architchture Only 设置为No
  • TARGETS->Build Settings->Other Linker Flags,添加 -ObjC
  • TARGETS->Build Settings->Enable Bitcode 设置为No
  • Edit scheme-Run-Build Configuration设置为Release

小结

1.尽量不要用xib,storyboard不同版本Xcode打包维护成本较高。
2.打包时Xcode版本尽量小于等于合作方的版本,可以避免一些宏找不到的问题。
3.同一份代码使用不同的Xcode版本打出来的大小是不一样的。
4.最终上线时要使用Release版的。
5.命名严格的按照Apple的命名规范来。

  • 一 易用性
    1、尽量都支持cocoapods
    2、API调用简单
    3、便于调试
    4、API回调参数明确(推荐返回model而非dictionary)
    5、API稳定
  • 二 API设计
    1、 参数命名一定要明确无歧义
    2、SDK配置参数和接口入参分开
    3、SDK参数:拼接的字符串方便扩展
    4、用于查询的属性,绝对不能直接设置(SDK会提供一些方法和属性,让接入者知道SDK的当前状态。常见的比如- (BOOL)islogin;@property(nonatomic, assign, readonly) BOOL isLogin;。方法可以隐藏属性,保证不被修改,如果是属性,一定要加readonly)
  • 三注意事项
    能用系统的API解决的,就不要使用第三方,减少对其他库的依赖
    OC没有命名空间,类命名和类别方法加上前缀
    黑科技虽然好,但是能不用的就不要用
    多考虑第三方带来的影响,比如键盘处理,UIKit的UIAppearance等依赖其他SDK的,别打包在一起,不然出现符号表重复使用了OC类别打包的时候记得加上-ObjC
    能不用单例的就尽量少的使用
    核心代码的安全性
    资源文件使用bundle进行管理,能不用xib的就别用了吧

关于使用 Swift 来开发 SDK

目前 Swift 3.0 版本是相对稳定,但实际上 Swift 变动也是会比较大,运行时也一直在变动,目测官方也没推荐单独用 Swift 来开发 SDK,但实际上我们还是可以使用 Swift 来开发 SDK 的,但兼容性这些就需要考虑,如果后继版本变动大的话,相对的维护成本也会比较高,这个就根据实际需要来选择了。这里就不单独提供 Swift sdk 的 demo 了, 有兴趣的可以参考下前面用 OC 写 sdk 的文章来写。

瘦身

如果你的Framework是从主包中脱离出来的一个模块,或者你的Framework已经迭代了好多个版本,难免会有许多的冗余。一般合作方对于包的大小都有要求,因此我们可以从这几个方面去入手。
1.从资源文件下手剔除不必要的资源,如图片,xib ,音视频等。
这里我们可以使用LSUnusedResources,找出Framework中没有使用的资源将其删掉。
2.也可以利用TinyPNG对项目要用的图片进行压缩。
3.可以从项目中的文件入手,利用LinkMap软件可以清晰的看到每个类的大小,这为我们删除类提供了依据,也可以利用上面.o的方法来查看,利用软件更加直观方便。
4.可以通过设置关于打Framework相关参数,如打Release版本的。
iOS之开发的SDK(.framework)瘦身

关于架构

1、模拟器架构:2种
       i386   : 32位架构      4S ~ 5
       x86_64 : 64位架构      5S ~ 现在的机型
2、真机架构: 3种
       armv7 : 32位架构       3GS ~ 4S
       armv7s: 特殊的架构      5 ~ 5C   <此架构已被Apple废弃掉,因此我们在打SDK时可以不兼容>
       amr64 : 64位架构       5S ~ 现在的机型

模拟器架构:
i386 : 4s / 5 目前已经没有该模拟器了,所以用模拟器编译的架构都是x86_64
x86_64 : 5s ---> xs max
真机架构:
armv7: 4 / 4s
armv7s: 5 / 5c 最特殊的一代 默认已经不支持了
arm64: 5s ---> xr max

关于架构我们可以看官方的这幅图,也看可以从这里查看详情。

iOS Framework制作方法_第4张图片
image

SDK编译

以模拟器编译时,会生成对应模拟器架构的SDK( i386,x86_64);
以Generic iOS Device编译时,会生成真机架构的SDK(arm7,arm64)。
脚本的作用是将这两个sdk合成一个,使的同时适用于真机和模拟器。

集成动态库上传AppStore

由于 iOS 编译的特殊性,为了方便开发者使用,我们将 i386, x86_64, armv7, arm64 几个平台都合并到了一起,所以使用动态库上传 appstore 时需要将 i386 , x86_64 两个平台删除后,才能正常提交审核

首先进入到Launchpad中,找到其他—打开终端,然后cd到SDK的所在目录。简单的方式就是找到项目中的环信SDK,然后终端先输入cd,然后按空格键,将环信SDK拖拽到终端内,会自动生成SDK的路径,然后环信SDK名称.framework删除掉,不要cd到环信SDK,只cd到SDK所在的目录下即可。

示例:比如环信SDK的路径是:/Users/easemob-dn0164/Desktop/iOS_IM_SDK_V3.6.0/HyphenateFullSDK/Hyphenate.framework 那么只需要cd到/Users/easemob-dn0164/Desktop/iOS_IM_SDK_V3.6.0/HyphenateFullSDK/ 就可以了。

后续在 SDK 当前路径下执行以下命令删除i386, x86_64两个平台
bak 文件是备份目录,上传appstore之后需要替换回 bak 目录下的 SDK
实时音视频版本Hyphenate.framework

mkdir ./bak
cp -r Hyphenate.framework ./bak
lipo Hyphenate.framework/Hyphenate -thin armv7 -output Hyphenate_armv7
lipo Hyphenate.framework/Hyphenate -thin arm64 -output Hyphenate_arm64
lipo -create Hyphenate_armv7 Hyphenate_arm64 -output Hyphenate
mv Hyphenate Hyphenate.framework/

不包含实时音视频版本 HyphenateLite.framework

mkdir ./bak
cp -r HyphenateLite.framework ./bak
lipo HyphenateLite.framework/HyphenateLite -thin armv7 -output HyphenateLite_armv7
lipo HyphenateLite.framework/HyphenateLite -thin arm64 -output HyphenateLite_arm64
lipo -create HyphenateLite_armv7 HyphenateLite_arm64 -output HyphenateLite
mv HyphenateLite HyphenateLite.framework/

上架APPStore

采用动态库开发,上传appstore时需要将i386 x86_64两个平台删除后,才能正常提交。删除方式参考 《http://docs.easemob.com/im/300iosclientintegration/20iossdkimport 集成动态库上传AppStore》。
cd 到framework的当前目录下 利用lipo -info SDKDemo.framework/SDKDemo查看支持的架构。

  • arm7: 在支持iOS7之前的设备上使用
  • arm7s: 在iPhone5和iPhone5C上使用
  • arm64: 在iPhone5S以上的64位ARM处理器上使用
  • i386: 在32位模拟器上使用
  • x86_64: 在64位模拟器上使用
// xx 代表framework的名字
lipo xx.framework/xx   // 查看framework支持的架构
// 输出 armv7
lipo xx.framework/xx -thin armv7 -output xx_armv7
// 输出 arm64
lipo xx.framework/xx -thin arm64 -output xx_arm64
// 合并
lipo -create xx_armv7 xx_arm64 -output xx
// 移动覆盖
mv xx xx.framework/

删除后,查看sdk支持的架构时 只有arm7arm64,没有arm7s。查询了百度地图等主流SDK后均没有对arm7s提供支持,具体原因未知。运行工程时,Xcode会打印一系列警告,不影响上架,具体原因未知。

去除x86_64架构提交APPStore
打包app时去掉二进制的i386 x86_64
iOS 打包移除 i386 和 x86_64 平台动态库
如何辨别.framework是动态库还是静态库
iOS Dynamic Framework 对App启动时间影响实测
SDK开发中解决sdk和app项目中都使用某个第三发库引发的冲突

你可能感兴趣的:(iOS Framework制作方法)