首先我们通过新建菜单的 Framework & Library 创建一个 Cocoa Touch Framework 项目QJWiFi
1、内容:
创建需要打包的代码,将需要公开调用的接口方法声明为public(供其他 module 调用)
2、framework 生成:
将运行设备选择为任一 iOS 模拟器,然后使用 Shift + Cmd + I
进行 Profiling 编译(同时生成 debug 与 release 版本,如果是 Cmd + B
,则只生成 debug 版本)。我们可以在项目的生成的数据文件夹 中找到QJWiFi.framework
快捷访问生成文件(对应项目的 ~/Build/Products/Release-iphonesimulator)
3、版本兼容:
将运行设备选择为真机,使用 Shift + Cmd + I
进行 Profiling 编译,此时我们的生成文件目录下有(Debug-iphonesimulator、Release-iphoneos、Release-iphonesimulator)三个文件,我们需要将其中的一些内容合并
合并A:合并 Release-iphoneos 与Release-iphonesimulator 文件下的二进制文件
终端命令:
cd /Users/xxx/Library/Developer/Xcode/DerivedData/QJWiFi-fejnkmidkzkbocbjnkbgoclwbobz/Build/Products
lipo -create Release-iphoneos/QJWiFi.framework/QJWiFi Release-iphonesimulator/QJWiFi.framework/QJWiFi -output Release-iphoneos/QJWiFi.framework/QJWiFi
lipo -info QJWiFi // 查询framework 支持的 cpu 架构
Architectures in the fat file: QJWiFi are: i386 x86_64 armv7 arm64
合并B:拷贝Release-iphonesimulator/QJWiFi.framework/Modules/QJWiFi.swiftmodule 文件夹下的所有文件到 Release-iphoneos 相应的文件夹中,现在 Release-iphoneos 文件中的 QJWiFi.framework 就是我们需要的架包。
4、测试:
新建一个 Swift 项目, 将 QJWiFi.framework 拖拽添加到项目中。我们最好勾选上 Copy items if needed,这样原来的框架的改动就不会影响到我们的项目了。然后,在需要使用这个框架的地方导入框架的 module(import QJWiFi),这样我们就可以使用使用框架中的公开类与方法。
但是。。。运行项目,success 之后编译器会报以下错误
dyld: Library not loaded: @rpath/QJWiFi.framework/QJWiFi
Referenced from: /Users/laichunhui/Library/Developer/CoreSimulator/Devices/CBBB7623-1930-4A1F-A094-6A2AC27A8E29/data/Containers/Bundle/Application/AB2EAE28-C094-4047-9379-815980E8A214/QJWiFiDemo.app/QJWiFiDemo
Reason: image not found
这是因为我们还未将框架复制到项目包中。在 Build Phases 选项卡里添加一个 Copy File 的阶段 ,然后将目标设定为 Frameworks,将我们的 QJWiFi.framework 添加到新建的阶段里,来指定 IDE 在编译时进行复制。
常见问题:
-
Objective-C 项目集成 Swift framework 注意点
如果要将框架导入到 OC 项目中(#import "QJWiFi/QJWiFi.h" 或 #import "QJWiFi/QJWiFi-Swift.h"),还需要将 Build setting 中的 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES 设置为 YES,否则项目会报 image not found 的错误。
-
资源加载
- framework 自身对应的 bundle: Bundle(for: QJWiFi.self)
- framework 内部 image 访问: UIImage(named: imageName, in: bundle, compatibleWith: nil)
- 报错: Include of non-modular header inside framework module
如果我们项目中调用了比如 CommonCrypto 等底层框架,由于这些框架并未打包成 module,我们无法直接导入到 Swift 项目中,如果在 framework 的头文件中直接导入 (#import <CommonCrypto/CommonCrypto.h>)就会报以上错误。在framework 中,桥接是不被允许的,有兴趣的可以不妨一试。所以我们只能为这个底层框架创建 module。
- 首先在你的 Framework/Target 下建一个文件夹,可以叫做 CommonCrypto ,并创建两个子文件夹,可以分别命名为 iphoneos 、iphonesimulator,并分别新建一个 module.modulemap的文件,内容分别为:
module CommonCrypto [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h"
export *
}
module CommonCrypto [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h"
export *
}
- 然后在你的 Target 的 Build Setting 中找到 Swift ComCompiler - Search Paths 的 Import Paths ,设置键值:
-
Any iOS Simulator SDK
${SRCROOT}/QJWiFi/CommonCrypto/iphonesimulator -
Any iOS SDK
${SRCROOT}/QJWiFi/CommonCrypto/iphoneos
-
这样在 framework 中就可以直接导入 module (import CommonCrypto)
网友评论