编程进阶网 编程进阶网
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • Android提升进阶

  • iOS开发和进阶

    • README
    • ObjC编程入门

    • Swift编程入门

    • iOS入门到精通

      • iOS入门到精通案例
      • UIKit框架原理探索
      • UIViewController
      • 项目工程面板说明
      • 通信实践和设计思想
      • 网络请求和数据解析
      • 多线程实践和原理
      • Swift和OC混编开发
      • Swift版SnapKit布局
      • 开发SDK实践设计
        • 01.开发SDK介绍
          • 1.1 SDK封装方式
          • 1.2 静态和动态库
          • 1.3 静态库的特点
          • 1.4 动态库的特点
          • 1.5 framework
        • 02.创建&配置三方库
          • 2.1 创建framework
          • 2.2 开发代码实践
          • 2.3 头文件管理
          • 2.3.1 头文件引入
          • 2.3.2 设置Headers Phase
          • 2.4 配置framework
          • 2.4.1 Mach-O Type 类型
          • 2.5 构建Framework
          • 2.5.1 直接编译构建
          • 2.5.2 脚本进行构建
          • 2.5.3 合并真机和模拟器
          • 2.6 SDK中资源文件
          • 2.7 XCFramework
          • 2.7.1 用脚本打包
          • 2.9 Framework签名
          • 2.10 Framework混淆
        • 03.引用第三方库
          • 3.1 引用framework
          • 3.2 测试framework
          • 3.3 边开发边调试SDK
          • 3.4 依赖库重复bug
          • 3.5 SDK间相互依赖
        • 04.一些常见的错误
          • 4.1 未找到相关SDK
          • 4.2 头文件报错
          • 4.3 三方库头文件缺失
          • 4.4 混编头文件报错
          • 4.5 依赖SDK的报错
        • 参考博客
      • iOS经验类笔记积累
  • Web开发和进阶

  • Linux应用开发

  • Apps
  • iOS开发和进阶
  • iOS入门到精通
杨充
2025-06-03
目录

开发SDK实践设计

# 16.开发SDK实践设计

# 目录介绍

  • 01.开发SDK介绍
    • 1.1 SDK封装方式
    • 1.2 静态和动态库
    • 1.3 静态库的特点
    • 1.4 动态库的特点
    • 1.5 framework
  • 02.创建&配置三方库
    • 2.1 创建framework
    • 2.2 开发代码实践
    • 2.3 头文件管理
    • 2.4 配置Framework
    • 2.5 构建Framework
    • 2.6 SDK中资源文件
    • 2.7 XCFramework
    • 2.8 混编Framework
    • 2.9 Framework签名
    • 2.10 Framework混淆
  • 03.引用第三方库
    • 3.1 引用framework
    • 3.2 测试framework
    • 3.3 边开发边调试SDK
    • 3.4 依赖库重复bug
    • 3.5 SDK间相互依赖
  • 04.一些常见的错误
    • 4.1 未找到相关SDK
    • 4.2 头文件报错
    • 4.3 三方库头文件缺失
    • 4.4 混编头文件报错
    • 4.5 依赖SDK的报错

# 01.开发SDK介绍

# 1.1 SDK封装方式

iOS封装SDK是指将iOS应用程序的功能封装成一个库,供其他开发者使用。

SDK可以提供一些接口和方法,使得其他开发者可以在不了解具体实现细节的情况下,直接使用这些功能。

iOS封装SDK的方式主要有以下几种:

  1. 静态库:静态库是将SDK的代码编译成一个静态库文件,其他开发者可以将其链接到自己的应用程序中使用。静态库的优点是使用方便,缺点是无法动态更新和修改。
  2. 动态库:动态库是将SDK的代码编译成一个动态库文件,其他开发者可以将其链接到自己的应用程序中使用。动态库的优点是可以动态更新和修改,缺点是使用相对复杂。
  3. 框架:框架是将SDK的代码打包成一个框架文件,其他开发者可以将其导入到自己的应用程序中使用。框架的优点是使用方便,缺点是无法动态更新和修改。

# 1.2 静态和动态库

静态库 VS 动态库

  1. 静态库在编译时将代码拷贝进目标程序中,会导致目标程序的体积增加。被多次使用就会在内存中存在多份冗余拷贝。
  2. 动态库在App冷启动时需要加载动态链接库,进行rebase指针调整和bind符号绑定等工作,会导致App的启动时间增长。由系统动态加载到内存,供App调用,系统只加载一次,多个程序共用,节省内存。
  3. iOS中静态库的形式:.a 和 .framework,一般开发者做的framework是静态库。
  4. iOS中动态库的形式:.dylib 和 .framework,一般iOS系统中的framework是动态库。

.a VS .framework

  1. .a是纯二进制文件 .framework中除了二进制文件还有资源文件
  2. .a文件不能直接使用,需要引入.h文件配合 .framework文件包含了.h文件和其他文,可以直接使用
  3. .a文件是静态库,.framework 既可以是静态库也可以是动态库

# 1.3 静态库的特点

平时我们用的第三方SDK基本上都是静态库,静态库的几个特点:

  1. 在App项目编译的时候会被拷贝一份编译到目标程序中,相当于将静态库嵌入了,所以得到的App二进制文件会变大。
  2. 在使用的时候,需要手动导入静态库所依赖的其他类库。(比如说某个SDK中使用到了CoreMotion.framework,在使用的时候需要手动导入。有的SDK需要link十几个系统库,这个时候非常恶心,只能一个一个手动加,这是静态库一个很大的不便之处。)
  3. 导入静态库的应用可以减少对外界的依赖,如果导入的是第三方动态库,动态库找不到的话应用就会崩掉,例如Linux上经常出现的lib not found。
  4. 静态库很大的一个优点是减少耦合性,因为静态库中是不可以包含其他静态库的,使用的时候要另外导入它的依赖库,最大限度的保证了每一个静态库都是独立的,不会重复引用。

# 1.4 动态库的特点

使用频率最高的UIKit.framework和Foundation.framework都属于动态库,所有.dylib和.tbd结尾的都属于动态库。动态库的几个特点:

  1. 这些库是所有应用公用的,换一种说法就是节省了应用安装包的体积,这是区别静态库很重要的一个特点,因为静态库使用一次就要拷贝一次,非常浪费资源。
  2. 动态库在制作的时候可以直接包含静态库,也能自动link所需要的依赖库。
  3. 使用动态库的时候不需要再次link依赖库,即导即用,这个就厉害了。唯一需要注意的是在导入自己制作的动态库时,需要在Embedded Binaries中导入,不然会报错:image not found。此时这个动态库会跟静态库一样被拷贝到目标程序中进行编译,苹果又把这种Framework叫做Embedded Framework

# 1.5 framework

Framework 实际上是一种打包方式,将库的二进制文件,头文件和有关的资源文件打包到一起,方便管理和分发。

Framework的英文释意是框架,主要由Headers、binary文件、.bundle这三部分构成,除此之外还有Info.plist和Modules,后两者主要记录Framework的版本之类的信息,一般都会删掉,不做讨论

  1. Headers:包含我们在制作Framework的时候暴露的头文件,所有被暴露的.h都放在这里。
  2. binary文件:整个Framework的核心,所有代码都被编译成了这样一坨二进制文件,这里要注意的是添加的依赖库不会被编译进来,用的时候还需要重新link其他依赖库。
  3. .bundle:资源文件都打包放在这里。

# 02.创建&配置三方库

# 2.1 创建framework

创建一个project项目,取名为 WxPalmSdk,选择 Framework & Library 中的 Framework,然后开始配置第三方库的包名,语言选择swift或者oc。

# 2.2 开发代码实践

swift不像OC可以暴露接口,在swift中要想给别的工程调用接口,记得在类,方法或属性前加public或者open。先测试一个小的案例,代码如下所示:

open class PalmHelper {
    //获取屏幕分辨率
    static func getResolution() -> CGSize {
        let screenSize = UIScreen.main.bounds.size
        let scale = UIScreen.main.scale
        let resolution = CGSize(width: screenSize.width * scale, height: screenSize.height * scale)
        return resolution
    }
}
1
2
3
4
5
6
7
8
9

# 2.3 头文件管理

# 2.3.1 头文件引入

通过如上方式创建SDK工程,这里我创建名为 WxPalmSdk 的SDK工程

生成的工程中有 WxPalmSdk.h 这一个头文件,一般我们将需要暴露的头文件都放在这个头文件中,以供外部调用。作用相当于项目中统一管理头文件的那个文件。

#import <Foundation/Foundation.h>

//! Project version number for AirPalmLib.
FOUNDATION_EXPORT double AirPalmLibVersionNumber;

//! Project version string for AirPalmLib.
FOUNDATION_EXPORT const unsigned char AirPalmLibVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <AirPalmLib/PublicHeader.h>

//将要暴露的头文件在此处引用
//默认生成的.h文件中,我的是 AirPalmLib.h,把所有需要暴露的.h文件都用#import 引入
//记住一定要将所有需要暴露的.h文件都引入,也就是上面Headers-Public中加的所有.h文件,不然编译后生成的.framework在引用的时候会有警告。

#import <WxPalmSdk/WeCardPalmHelper.h>
#import <WxPalmSdk/PalmWebViewController.h>
#import <WxPalmSdk/PalmRegisterViewController.h>
#import <WxPalmSdk/BeanAuthData.h>
#import <WxPalmSdk/BeanLicense.h>

//第三方头文件暴露
#import <AFNetworking/AFNetworking.h>
#import <AFNetworking/AFURLRequestSerialization.h>
#import <WechatOpenSDK/WXApi.h>
#import <WechatOpenSDK/WXApiObject.h>
#import <WechatOpenSDK/WechatAuthSDK.h>
#import <AlipaySDK/AlipaySDK.h>

//错误示范
#import <WXApi.h>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 2.3.2 设置Headers Phase

如果你希望将Framework提供给其他开发者使用,你需要确保Framework的可见性设置正确。

在项目设置中,选择"Build Phases",展开"Headers",然后将需要公开的头文件拖拽到"Public"区域。

  1. Public:需要暴露出来的 h 文件
  2. Private:不想公开的 h 文件
  3. Project:显示你的Framework里面的所有你创建的 h 文件

# 2.4 配置framework

  1. 在Build Settings设置中,Targets → General → Minimum Deployments设置为 iOS 11.0/9.0
  2. 在Build Settings设置中,【必须】Build Active Architecture Only 仅构建活动架构,这个要设置为NO。意思是当前打包的.framework支持所有的设备,否则打包时只能用当前版本的模拟器或真机运行。
  3. 在Build Settings设置中,Excluded Architecture 排除架构,如果没有特定架构设置则不用管
  4. 在Build Settings设置中,Dead Code Stripping 死代码剥离,即编译选项优化,对于framework来说, 应该设置为NO, 避免代码、调试符号等被剥离。
  5. 在Build Settings设置中,Mach-O Type 类型,设置类型为静态库Static Library【必须】
  6. 在Build Settings设置中,Build Libraries for Distribution 为分发构建库,设置为Yes,使编译出来的framework向下兼容。
  7. 在Build Settings设置中,Link With Standard Libraries,设置成 No,避免重复链接
  8. 在Build Settings设置中,Build Settings → Enable Bitcode 设置为 No
  9. 在Build Settings设置中,Excluded Architectures → Release,添加 Any iOS Simulator SDK 配置 arm64
  10. 在Build Settings设置中,Build Libraries for Distribution 设置为Yes (如果是swift语言的时候需要)
  11. 在菜单Product → Scheme → Edit Scheme → Run → 修改 Build Configuration 编译 为 Release

# 2.4.1 Mach-O Type 类型

在 iOS 开发中,Mach-O(Mach Object)是一种可执行文件格式,用于存储可执行程序、动态链接库和静态库等二进制文件。Mach-O 文件包含了程序的代码、数据、符号表等信息,以及用于动态链接的信息。

Mach-O 文件有不同的类型(Mach-O Type),常见的类型包括:

  1. Executable(可执行文件):包含可执行程序的二进制代码,可以直接运行。
  2. Dynamic Library(动态库):包含可共享的代码和数据,可以在运行时被动态加载到内存中。
  3. Static Library(静态库):包含编译后的代码和数据,可以被静态链接到可执行文件中。
  4. Bundle(捆绑包):包含资源文件、代码和数据等,通常用于存储插件或应用程序的资源。
  5. Framework(框架):是一种特殊的 Bundle,通常包含动态库、头文件和资源文件等,用于组织和共享代码。

# 2.5 构建Framework

  1. 第一种方式:选择"Product" -> "Build"来构建Framework。Xcode将会编译你的代码,并生成Framework文件。
  2. 第二种方式:创建打包工程Aggregate,然后使用脚本进行构建输出。
  3. 第三种方式:写一个shell脚本,然后使用特定的指令进行构建输出Framework

# 2.5.1 直接编译构建

打包Framework:分为真机和模拟器,这两个生成的framework是不一样的。(如果说你需要生成一个既可以真机使用又可以模拟器使用的,那就分别生成,最后在合并在一起)。

按照将编译的 Device 选择为真机 ,然后按下 Command + B 开始编译,编译成功后右键 Products 文件夹下的 .framework 文件,点击 Show in Finder。

# 2.5.2 脚本进行构建

  1. 第一步:创建打包工程 Aggregate。然后在 Build Phases -> Target Dependencies 中添加需要依赖的SDK
  2. 第二步:创建 Run script。在 Build Phases -> + -> New Run Script Phase 中添加脚本
  3. 第三步:在 Edit Scheme 中,修改在release环境下进行构建。在 Build Phases 选项中,在 Target Dependencies 中添加依赖的target。参考博客 (opens new window)
#测试该脚本是可用,仅需要修改TARGET_NAME名称即可
TARGET_NAME="AirPalmLib"
#TARGET_NAME=${PROJECT_NAME}
# ${PWD}是一个Shell变量,表示当前工作目录的路径。
PROJECT_FILE_PATH="${PWD}/${PROJECT_NAME}/${TARGET_NAME}.xcodeproj"
CONFIGURATION="Release"
BUILD_DIR="${PWD}/Build"
OBJROOT="${BUILD_DIR}/Intermediates"
BUILD_ROOT="${BUILD_DIR}/Products"
IPHONE_DEVICE_BUILD_DIR="${BUILD_ROOT}/${CONFIGURATION}-iphoneos"
SYMROOT="${BUILD_ROOT}"

#-project "${PROJECT_FILE_PATH}":指定要构建的Xcode项目文件的路径。
#-target "${TARGET_NAME}":指定要构建的目标的名称。
#-configuration "${CONFIGURATION}":指定要使用的构建配置的名称,例如Debug或Release。
#-sdk iphoneos:指定要构建的目标SDK,这里是iPhoneOS。
#BUILD_DIR="${BUILD_DIR}":指定构建输出的目录。
#OBJROOT="${OBJROOT}":指定Objective-C文件的编译输出目录。
#BUILD_ROOT="${BUILD_ROOT}":指定构建根目录。
#CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/arm64":指定构建输出的目标设备目录,这里是针对arm64架构的设备。
#SYMROOT="${SYMROOT}":指定符号文件的输出目录。
#ARCHS='arm64':指定要构建的架构,这里是arm64。
#VALID_ARCHS='arm64':指定有效的架构,这里是arm64。
#这个命令的目的是使用xcodebuild工具根据指定的参数和选项来构建iOS项目。

xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/arm64" SYMROOT="${SYMROOT}" ARCHS='arm64' VALID_ARCHS='arm64'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 2.5.3 合并真机和模拟器

真机使用 ARM 架构,而模拟器使用 x86 架构。因此,如果您只编译了真机或模拟器版本的 Framework,那么它只能在相应的设备上运行。

合并真机与模拟器编译后的framework文件通过lipo -create 命令合并:

lipo -create + 模拟器编译后的framework中的 TestSDK + 真机编译后的framework中的 TestSDK + -output + 合并之后要保存的路径
1

合并操作目的,创建一个包含多个架构的通用 Framework,以便在不同的设备上使用。

# 2.6 SDK中资源文件

iOS之Bundle的创建有三种方式:

  1. 第一种方式:自己新建一个文件夹,将文件夹的后缀改成.bundle,然后将此bundle拖入到工程中,然后往工程中的.bundle底下添加素材即可
  2. 第二种方式:在工程中添加Target,此Target为bundle
  3. 第三种方式:直接创建一个工程,此工程为bundle

iOS之Bundle的创建与使用:https://www.jianshu.com/p/dd73925b02e7

iOS:NSBundle的一些理解:https://www.jianshu.com/p/b64ff9d8e7ce

# 2.7 XCFramework

Framework(框架)和 XCFramework 是两种用于打包和分发代码的不同格式。

Framework(框架):Framework 是一种用于打包和分发代码的格式,最常见于 iOS 和 macOS 开发。它是一个包含二进制文件、资源文件和头文件的目录结构。Framework 可以包含多个架构(如 arm64、x86_64 等),以支持不同的设备和平台。开发者可以将 Framework 集成到应用程序中,以便在应用程序中使用其中的代码和资源。

XCFramework:XCFramework 是苹果在 Xcode 11 中引入的一种新的打包格式。它是一种跨平台的二进制分发格式,可以同时支持多个平台(如 iOS、macOS、watchOS 和 tvOS)。XCFramework 可以包含多个 Framework,每个 Framework 都针对特定的平台和架构进行优化。这使得开发者可以更方便地在不同平台之间共享和分发代码。

主要的区别在于 XCFramework 是一种跨平台的分发格式,可以同时支持多个平台,而 Framework 是一种特定于 iOS 和 macOS 的分发格式。

# 2.7.1 用脚本打包

以下是一个示例脚本,用于在 iOS 上使用 xcodebuild 命令打包 XCFramework,该脚本可用:

# 清理旧的构建目录
rm -r build
# 创建构建目录
mkdir build

echo 'xcodebuild device'
# 构建 iOS 真机版本
xcodebuild archive \
  -scheme WxPalmSdk \
  -configuration Release \
  -destination 'generic/platform=iOS' \
  -archivePath './build/WxPalmSdk.framework-iphoneos.xcarchive' \
  SKIP_INSTALL=NO \
  BUILD_LIBRARIES_FOR_DISTRIBUTION=YES

echo 'create xcframework'
# 创建 XCFramework
xcodebuild -create-xcframework \
  -framework './build/WxPalmSdk.framework-iphoneos.xcarchive/Products/Library/Frameworks/WxPalmSdk.framework' \
  -output './build/WxPalmSdk.xcframework'

echo 'zipping...'
# 压缩 XCFramework
cd build
zip -r WxPalmSdk.xcframework.zip WxPalmSdk.xcframework
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

xcodebuild archive,这个命令是构建iOS真机,具体一些配置属性如下:

  • 构建 iOS 真机版本的框架。构建结果将被存档到 "./build/WxPalmSdk.framework-iphoneos.xcarchive"。
  • SKIP_INSTALL=NO 表示构建过程中会执行安装操作,将构建结果安装到 DerivedData 目录中。
  • BUILD_LIBRARIES_FOR_DISTRIBUTION=YES 表示构建的库将用于分发,这将确保构建的框架包含必要的符号信息和支持库。

xcodebuild -create-xcframework,这个命令用于创建 XCFramework 的命令,具体一些参数解释如下:

  • -framework 参数指定了要转换的框架路径
  • -output 参数指定了输出的 XCFramework 路径,即 ./build/WxPalmSdk.xcframework。

# 2.9 Framework签名

静态 Framework(.framework)是否需要签名,取决于它的使用场景和分发方式。

  1. 静态 Framework 仅用于开发阶段(例如,作为项目的依赖库),不需要签名。
  2. 如果静态 Framework 是作为独立的二进制文件分发给第三方开发者使用,则 不需要签名。第三方开发者在使用时,会将其集成到自己的项目中,并在最终打包时签名。
  3. 如果静态 Framework 是用于企业分发或 Ad Hoc 分发的 App 的一部分,则 需要签名。

# 2.10 Framework混淆

静态 Framework(.framework)的混淆是为了保护代码逻辑,防止逆向工程。由于静态 Framework 是编译后的二进制文件,混淆的方式与源代码混淆有所不同。

  1. 使用符号表剥离(Strip Symbols),通过剥离符号表,可以移除二进制文件中的调试符号和未使用的符号,使逆向工程更加困难。

# 03.引用第三方库

# 3.1 引用framework

第一种:直接引用系统提供的.framework

  1. 选中项目名称
  2. 选中TARGETS
  3. 选中Build Phases
  4. 在Link Binary With Libraries中添加。
  5. 点击“+”号,加入所需的系统提供的.framework文件

第二种:引用第三方提供的.framework

  1. 下载好所需要的第三方提供的.framework
  2. 将第三方.framework文件拷贝到工程所处的文件夹中
  3. 一定要注意:在 General —> Frameworks,Libraries,and Embedded Content,选中该第三方framework后,设置为 Embed & Sign

具体可以看:https://www.cnblogs.com/Free-Thinker/p/9524876.html

第三种:引入第三方提供的.xcframework

  1. 将生成的xcframework文件拖放到您的Xcode项目中的合适位置。
  2. 在"General"选项卡的"Frameworks, Libraries, and Embedded Content"部分,点击"+"按钮,选择"Add Other..."选项。然后,浏览并选择您之前添加的xcframework文件。
  3. 在"Build Settings"选项卡中,确保您的目标的"Framework Search Paths"设置包含xcframework所在的文件夹路径。
  4. 使用import语句导入xcframework中的框架。然后,您可以使用这些框架中提供的类、方法和功能。

# 3.2 测试framework

调用工程中,我们只需在要用到 WxPalmSdk.framework的页面导入头文件即可

# 3.3 边开发边调试SDK

# 3.4 依赖库重复bug

# 3.5 SDK间相互依赖

倘若SDKA 依赖于 SDKB,同时SDKA、SDKB也同时依赖SDKC,那么在制作SDKA的时候,只需要在SDK中加入SDKB,但是SDKB的头文件中要引入SDKC。如

//这个是SDK中依赖头文件
#import <AirPalmLib/WeCardPalmHelper.h>
#import <AirPalmLib/PalmWebViewController.h>

//这个是微信sdk中的头文件
#import <AirPalm/AirPalmKit.h>
#import <AirPalm/DBAirPalmInitParams.h>
1
2
3
4
5
6
7

# 04.一些常见的错误

# 4.1 未找到相关SDK

Could not build module:导致该错误的原因有很多,常见的可从以下中进行排查

  1. Framework路径是否正确,主要是检查,Framework Search Paths 中路径是否正确
  2. SDK的依赖关系是否正确
  3. 所依赖的SDK是否可通过单独编译
  4. 外部引用的依赖的SDK的头文件是否暴露

"Framework Search Paths" 配置项允许您自定义框架搜索路径,以便在项目中使用自定义框架或将框架放置在非标准位置。这对于使用自定义框架或将框架放置在非标准位置的情况非常有用。

# 4.2 头文件报错

假设我们引入了一个自定义的 Framework,尝试导入其中的头文件:

#import <MyCustomFramework/MyCustomFramework.h>
1

如果编译时出现如下错误:‘MyCustomFramework/MyCustomFramework.h’ file not found,则意味着 Xcode 找不到该头文件。

  1. 确认动态库正确引入。按照引用framework在检查一下依赖的步骤
  2. 检查 Header Search Paths。动态库引用的头文件需要通过 “Header Search Paths” 来找到。如果没有设置,Xcode 将不知道去哪里寻找。
2.1 选中项目文件,切换到 Build Settings。
2.2 搜索 Header Search Paths。用于指定编译器在搜索头文件时应查找的路径。
2.3 确保你的动态库的头文件路径(一般是 $(PROJECT_DIR)/Path/To/YourFramework)已经添加到这里。
1
2
3
  1. 确保 Framework 的可访问性。Framework 的属性可能设定为 “No” 而非“Public”。确保动态库的设定为“Public”,这样其他模块才能访问它的头文件。

# 4.3 三方库头文件缺失

使用cocoapods引入AFNetworking等后,在工程中import时找不到对应的头部

错误描述:error: 'AFNetworking.h' file not found (in target 'AirPalmLib' from project 'AirPalmLib')

备注,在AirPalmLib这个framework中,通过pod依赖了AFNetworking库,在编译打包的时候总是报错'AFNetworking.h'头文件找不到

解决办法:在项目的Target的里设置一下,添加cocoapods头文件目录:目录路径直接写:${SRCROOT},后边选择recursive 。就可以了。

注意:是在 User Header Search Paths 里添加,不是上面的 Header Search Paths.

# 4.4 混编头文件报错

错误描述:xxx/WecardPaySDK.build/module.modulemap:9:10: error: header 'WecardPaySDK-Swift.h' not found

这个错误通常表示在编译过程中找不到名为 'WecardPaySDK-Swift.h' 的头文件。这个错误通常与 Swift 与 Objective-C 之间的桥接有关。

xxx-Swift.h 文件是当你使用Swift代码时,自动生成的头文件,它使得Objective-C代码可以调用Swift定义的类和方法。如何解决Swift混编的module头文件报错?

  1. 检查文件路径:首先,确保自动生成的Swift.h文件位于正确的位置。在Xcode中,该文件通常位于项目的DerivedData目录下的Build文件夹中。如果文件路径不正确,可以尝试重新生成Swift.h文件或手动将其复制到正确的位置。
  2. 检查Objective-C Bridging Header设置:在Xcode中,Objective-C Bridging Header是用于将Swift代码与Objective-C代码进行桥接的文件。确保在项目的Build Settings中正确设置了Objective-C Bridging Header路径,并且路径是相对于项目根目录的。
  3. 检查模块导入设置:如果自动生成的Swift.h文件中引用了其他模块或框架,确保这些模块或框架已正确导入到项目中。可以通过在Build Phases的Link Binary With Libraries中添加所需的模块或框架来解决此问题。
  4. 清理和重新构建项目:有时,编译器可能会出现缓存或其他问题,导致自动生成的Swift.h文件找不到。尝试清理项目并重新构建,以确保所有文件都正确生成。

# 4.5 依赖SDK的报错

依赖framework报错 Could not build module 'AirPalmLib',这样的错误通常意味着Xcode无法找到或正确链接到名为AirPalmLib的框架。

# 参考博客

  • iOS SDK(framework)开发:https://juejin.cn/post/7380513228046123044
  • iOS 创建framework依赖cocoapods:https://juejin.cn/post/7232187022398898234
  • iOS SDK封装Framework带资源文件封装:https://juejin.cn/post/6911226050102394894
  • [Swift]SDK开发:https://blog.csdn.net/wsyx768/article/details/128801353
  • XCFramework 深度使用(1)-Swift 静态库:https://juejin.cn/post/6891850436505485325
  • 在 iOS Swift 开发中 简单地使用 XCFramework:https://juejin.cn/post/7243272599768399932?searchId=2024121916074431BC4A1715ED66C43FDA
上次更新: 2026/06/10, 11:13:41
Swift版SnapKit布局
iOS经验类笔记积累

← Swift版SnapKit布局 iOS经验类笔记积累→

最近更新
01
信号崩溃快速排查
06-15
02
CoreDump破案
06-15
03
perf火焰图实战
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式