swift framework 制作

首先我们通过新建菜单的 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 在编译时进行复制。

常见问题:

  1. 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 的错误。


  2. 资源加载

  • framework 自身对应的 bundle: Bundle(for: QJWiFi.self)
  • framework 内部 image 访问: UIImage(named: imageName, in: bundle, compatibleWith: nil)
  1. 报错: 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)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 静态库与动态库的区别 首先来看什么是库,库(Library)说白了就是一段编译好的二进制代码,加上头文件就可以供别...
    吃瓜群众呀阅读 14,159评论 3 42
  • (原文:How to Create a Framework for iOS 作者:Sam Davies 译者:Mr...
    王宪岭阅读 10,399评论 3 23
  • 1.The business went belly up after only six months. 这家公司只...
    Mr_Oldman阅读 968评论 0 0
  • 深深感恩彩虹老师带领和分享,用教练技术这样可以内在测量的善巧工具,一步一步调整自己的身心状态。内在觉察更加精准具体...
    施雨希阅读 1,445评论 1 1
  • 大纲 一心想开个饭馆的小厨娘与不走寻常路的冷面杀手之间的二三事。 一,救命之恩。 杀手与厨娘的初相遇 二,杀手与...
    两柒阅读 2,744评论 0 0

友情链接更多精彩内容