本文是我在工做中开发 Framework 过程当中的对踩过的坑走过的弯路的总结,此教程 Swift 和 OC 都适用,文章末尾附可能遇到的问题以及解决方案,但愿给各位开发小伙伴一点帮助。ios
本文主要讲了一下内容:git
在咱们开发中最离不开的就是 Framework 好比 UIKit.framework,因此对 framework 应该是比较熟悉的,那么在开发中也常常把本身的所作模块的代码作成 framework,场景以下:github
连接时完整地拷贝至可执行文件中,被屡次使用就有多份冗余拷贝。swift
连接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。数组
静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被连接到目标代码中,程序运行时将再也不须要改静态库;而动态库在程序编译时并不会被连接到目标代码中,只是在程序运行时才被载入,由于在程序运行期间还须要动态库的存在。xcode
同一个静态库在不一样程序中使用时,每个程序中都得导入一次,打包时也被打包进去,造成一个程序。而动态库在不一样程序中,打包时并无被打包进去,只在程序运行使用时,才连接载入(如系统的框架如UIKit、Foundation等),因此程序体积会小不少,可是苹果不让使用本身的动态库,不然审核就没法经过。bash
下面就一步一步的演示如何制做一个 framework, 以及制做本身的 framework 中可能会遇到的坑,以及如何解决。做为演示作个比较简单的数组乱序的 framework架构
类名就取为 ArrayDisorder,而后新建完成app
open class ArrayDisorder: NSObject {
open func disorder (orders:Array<Any>) -> Array<Any> {
var temp = orders
var count = Int(temp.count)
while count > 0 {
let index = Int(arc4random_uniform(UInt32(Int32(count))))
let last = Int(count-1)
temp.swapAt(index, last)
count -= 1
}
return temp
}
}
复制代码
注意:也许你会发现 在 class 前面或者在disorder方法前有 open 关键字,说到这里先说下和这个地方和oc 制做 Framework 不一样的地方框架
//! Project version number for ArrayDisorderSDK.
FOUNDATION_EXPORT double ArrayDisorderSDKVersionNumber;
//! Project version string for ArrayDisorderSDK.
FOUNDATION_EXPORT const unsigned char ArrayDisorderSDKVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <ArrayDisorderSDK/PublicHeader.h>
上面的这句注释说的很清楚 若是你想让别人外面找到你在 framework 中的类你必须像 <ArrayDisorderSDK/PublicHeader.h> 这种格式同样把 你的类导入这文件中
复制代码
最后一句
// In this header, you should import all the public headers of your framework using statements like #import <ArrayDisorderSDK/PublicHeader.h>
复制代码
说的很清楚若是你想让别人外面找到你在 framework 中的类你必须像 <ArrayDisorderSDK/PublicHeader.h> 这种格式同样把 你的类导入这文件中,在编译成 SDK 以后生成的头文件中就能够看到你对外开放的类和方法
建立 Swift framework也会生成一个这样的文件可是 则不须要这样导入头文件。只须要在要暴露给使用者的类名和方法名前面写上 Open 或者 Public 当编译成 Framework 以后会生成 "你的 framework 的名字-Swift.h"的文件 在这个文件中你能够看到类名前面 表有 Public 或者 Open 关键字的类.
何时用 Open 何时用 Public?
Open 在做用域外是能够被访问,继承 ,用 Open 关键字修饰的开放类成员在做用域以外是可访问和可覆盖的。
Pubic 在做用域外是可访问的,但在做用域以外没有子类。公共类成员是可访问的,但在做用域以外是不可覆盖的。
点击 framework 的 target build settings - linking -> Mach-o Type -> Static Library 或者 Dynamic Library
在这个 Demo 中 设置为支持 iOS 8
走到这一步,基本 Framework 已经初步完成, Command + B
注意:编译的时候 选择的 Device 若是是模拟器 则生成的是 x86架构,仅支持模拟器,在真机上这个编译的 Framework 则不能用 ,若是 Device 不选或者选择你链接在电脑上的真机,则编译成的是arm64 能够在真机上跑可是不能用在模拟器,若是制做的 framework 须要在模拟器和真机上用,则须要把这两个架构合成一块,这个==待会下面详细讲.==
点击生成的 Framework 而后 Show In Finder
如图中所示,生成了ArrayDisorderSDK.framework 那么这个文件就能够直接给别人使用了.
在咱们写代码时通常都习惯于边写边调试,那么在制做 Framework 时有两种方法调试咱们的 Framework
新建一个名字是 testArrayDisorderDemo的 Progect 以下
直接把编译好的 Framework 拖入到 testArrayDisorderDemo中
而后 import ArrayDisorderSDK
在 ViewDidLoad 中写入以下代码
let disOrder = ArrayDisorder() //Framework 中的封装了乱序功能的类
//disOrder.disorder(orders: [1,2,3,4,5,6,7,8,9]) 调用ArrayDisorder 对外公布的类
print(disOrder.disorder(orders: [1,2,3,4,5,6,7,8,9]))
// 输出:[8, 6, 2, 5, 3, 4, 7, 9, 1]
复制代码
到此,咱们简单的 framework 就能够算完成了.
可是这中调试framework 的方法效率比较低,咱们每一次调试都须要从新把原来的 framework 从testArrayDisorderDemo中删除而后从新导入.这样比较麻烦.那么下面有一种比较方便高效的方法。
仍是testArrayDisorderDemo 这个测试 Framework 的工程
如图所示
而后把ArrayDisorderSDK 拖入到testArrayDisorderDemo 文件中 如图
而后打开testArrayDisorderDemo
-- > General ->Embedded Binaries-> 点击加号-> add Other -> 选中ArrayDisorderSDK.xcodeproj
以下图
)]
再选择 Target 的地方你会发现 如今已经有连个 Taeget 一个是testArrayDisorderDemo 一个是ArrayDisorderSDK
若是选中 testArrayDisorderDemo就是运行 Demo 若是选中ArrayDisorderSDK 就是编译 SDK
这时你会发现能够直接在testArrayDisorderDemo 的 ViewController 中直接 导入ArrayDisorderSDK就能够了 不须要在删除而后再拖入了. 最重要的是 ,当你选中的testArrayDisorderDemo Tagret 运行的时候 当程序走到 framework 中去的时候 你还能够打断点等方式调试. 效率会很高.
注意: 当你修改 framework 中的代码时要想测试下修改的效果,你必需先编译下你的 framework 的 target 如本文中所示的就要先编译下ArrayDisorderSDK的 target,不编译的话就至关于你的 测试你 framework 的 Demo 用的仍是原来的 framework 而不是修改后的
CPU 的架构在不一样的机型上有不一样的 主要有一下:
arm7: 在最老的支持 iOS7的设备上使用
arm7s: 在 iPhone 5 和 iPhone 5c 上使用
arm64: 在 iPhone 5s 的64位 ARM 处理器上
i386: 在32位模拟器上使用
x86_64: 在64位模拟器上使用
固然一个 Framework 不须要所有支持,能够根据须要.
如上文所说, 编译的时候 选择的 Device 若是是模拟器 则生成的是 x86架构,仅支持模拟器,在真机上这个编译的 Framework 则不能用 ,若是 Device 不选或者选择你链接在电脑上的真机,则编译成的是arm64 和 arm7 能够在真机上跑可是不能用在模拟器,若是制做的 framework 须要在模拟器和真机上用,则须要把这两个架构合成一块,那么这就须要合成架构了.
首先,咱们要了解,如何查看一个 framework 的架构
用命令: lipo -info
注意: -info 中 - 和 info 没有空格,info 后面有一个空格
如图所示
把ArrayDisorderSDK 文件拖入控制台 而后回车 控制台就能够输出ArrayDisorderSDK 的 CPU 架构 如 armv7 arm64
这个是支持真机的,若是支持模拟器则不行的,须要从新编译:
在上图中也能看到 当选中ArrayDisorderSDK.framework show in Finder 时你会发如今上一层有四个文件夹(最多为四个若是你只在 relesae 下真机上编译 就只有一个文件夹) ,主要分为 Debug 和 release 两种环境下的 真机和模拟器 Debug-iphoneos/ Debug-iphonesimulator Debug 下的模拟器 Release-iphoneos/Release-iphonesimulator relesase 下的真机和模拟器
那么咱们须要作的就是把Release-iphoneos/Release-iphonesimulator 下的两种架构合成一个
用命令: lipo -create aa bb -output cc 加入你framework 的名字是 ArrayDisorderSDK
aa: 表示Release-iphoneos 文件夹下的 ArrayDisorderSDK.framework/ArrayDisorderSDK 的路径 bb : Release-iphonesimulator 文件夹下的 ArrayDisorderSDK.framework/ArrayDisorderSDK
cc: 生成的文件名 是和你的 framework 同名的,好比叫ArrayDisorderSDK
生成的output 出来的ArrayDisorderSDK是须要把Release-iphoneos 文件夹下的 ArrayDisorderSDK.framework 的中的ArrayDisorderSDK 替换掉的.
注意:-create 以及-output 在 create 和 output前面以- 是没有空格,可是在create 和 output后面是有一个空格的
上面说的可能不太好懂,那么下面演示一下,化繁为简: 如图
总之这种方法仍是太麻烦的,容易出错,下面介绍另一种比较简单的.
而后在 脚本地址
下载一个名为universal-framework.sh 文件 把文件内容拷贝到如图所示
注意:universal-framework.sh 中 ${PROJECT_NAME} 要把这个换成你本身的 framework 的名字
设置完成以后 ,编译UniversalArrayDisorder target 编译成功以后,会自动打开一个生成 Framework 的文件夹,而后再查看架构信息你会发现,即支持真机也支持模拟器啦.
错误提示:
No such module xxx
复制代码
解决:
缘由就是 Framework Search Path 中的路径错了 能够参考 参考地址 解决方案手动设置 这个路径是你向引用你的 framework 的项目拖自定义的 framework 时自动生成的 因此简单的解决方案就是 删除 framework 从新拖入 注意:拖的时候必定要确保 framework 和目标项目在同一个文件夹下,这样就不会出问题了
错误提示:
'xxxx' is unavailable: cannot find Swift declaration for this class
xxxx 表示 framework 中的类名
复制代码
解决:
framework 的架构错误: 若是如你的 framework 须要在模拟器上跑 那么你的 framework 必须包含x86 若是还须要在真机上跑 那么必须包含arm64 架构 能够用命令检查架构 lipo -info 参考
错误提示:
Reason: image not found
Message from debugger: Terminated due to signal 6
复制代码
解决:
动态库 Embedded Binaries没有 添加 your framework name.framework -> 添加 若是是静态库 则不须要添加 如图
![]()
参考文献:
:https://medium.com/flawless-app-stories/getting-started-with-reusable-frameworks-for-ios-development-f00d74827d11
:https://medium.com/captain-ios-experts/develop-a-swift-framework-1c7fdda27bf1
:https://www.raywenderlich.com/65964/create-a-framework-for-ios
本文是在我开发中遇到的问题的一个总结,整体倾向与如何更方便高效的建立本身的 framework,对于 OC 和 Swift 建立 framework 的异同介绍较少,因为本文重点不在于此,有机会下次再总结. 因为工做繁忙,水平有限,不免有不全,或者说的不合适的地方,还请看到此文章的朋友不吝赐教.或者你对本文中有不理解的地方,都但愿在评论区交流. 若是此文解决了你的问题,还请点赞支持下。
Demo地址 欢迎转载,转载请注明出处:https://juejin.im/post/5a5269a3f265da3e347b15de