杰理 SDK 文档中心
首页
首页
  • 概述与快速开始

    • 仓库概览
    • 运行环境与 SDK 集成
    • 工程结构与目录导航
  • 核心 SDK 架构

    • SDK 库体系与模块划分
    • 蓝牙连接与 RCSP 协议
    • 广播包解析与设备认证
    • 日志助手与调试支持
  • 设备功能模块

    • OTA 固件升级
    • 表盘管理与自定义表盘
    • 图像转换工具
    • 资源打包
    • 音频编解码
    • 健康与运动数据同步
    • 消息通知与实用设备功能
  • 宜动健康示例应用

    • 应用架构与页面导航
    • 健康界面与数据可视化
    • 设备连接与数据同步
    • 登录注册与用户中心
    • AI 云服务与语音交互
    • 本地数据库与持久化
    • 多语言国际化
  • 测试与调试

    • SDKTestHelper 功能测试工具
    • 音频编解码示例工程
    • 调试技巧与问题排查
  • 文档与资源

    • 在线文档与版本历史
    • 第三方框架与依赖管理

第三方框架与依赖管理

本文档介绍 iOS-JL_Health 仓库中各个工程(主工程 JieliJianKang、SDKTestHelper、JLAudioUnitKitDemo)如何通过 CocoaPods 管理第三方依赖,包括依赖清单、版本策略、全局导入机制以及各框架在代码中的典型用法。

Purpose and Scope

本页覆盖以下内容:

  • 仓库内各工程使用的第三方框架清单、版本与用途
  • CocoaPods 的配置方式(Podfile、use_frameworks!、pod install)
  • 通过 @_exported import 实现的全工程全局导入机制
  • 第三方框架在业务代码中的实际调用方式(以 RxSwift、SnapKit、Kingfisher、Toast-Swift 等为例)

本页不涉及以下主题(由其他目录页负责):

  • JL 蓝牙健康 SDK 自身 API 的设计与使用(属于 SDK 能力页)
  • 各业务模块的业务逻辑(属于对应功能页)
  • 打包、签名、发布流程(属于工程配置/发布相关页)

Overview

iOS-JL_Health 是一个以 Jieli(杰理)蓝牙健康 SDK 为核心的 iOS 工程仓库,包含三个独立的 CocoaPods 工程:

工程目标名称定位
code/JL_HealthJieliJianKang主健康应用工程,面向最终用户
code/SDKTestHelperSDKTestHelperSDK 集成测试/调试辅助工程
code/JLAudioUnitKitDemoJLAudioUnitKitDemo音频单元组件 Demo 工程

三个工程共用一套依赖管理方式:CocoaPods。主工程与测试工程都通过 Podfile 声明依赖,并在工程根目录执行 pod install 生成 .xcworkspace 后编译。依赖分为两类:

  1. 通用 UI/响应式基础库:RxSwift、RxCocoa、SnapKit、Toast-Swift、FMDB 等,三个工程几乎都会用到;
  2. 工程特定库:如主工程使用 Kingfisher(图片加载)与 SwiftyAttributes(富文本),SDKTestHelper 额外使用 MJRefresh(下拉刷新)、WMZDialog(弹窗)、R.swift(资源类型安全)、Starscream(WebSocket)、Colours(颜色工具)以及杰理自研的 JLUsefulTools 私有 pod。

版本策略上,主工程对核心依赖锁定精确版本(如 RxSwift '6.6.0'),保证可重复构建;SDKTestHelper 作为测试工程则大多不锁版本,跟随最新兼容版本。

Architecture

下面用 Mermaid 图展示仓库内依赖管理的整体架构:三个工程分别通过各自的 Podfile 声明依赖,CocoaPods 解析后生成 Pods 工程与 workspace,业务代码通过 import/@_exported import 使用第三方框架。

flowchart TD
    subgraph sg_Projects["工程层 (Workspaces)"]
        JL["JieliJianKang<br/>(主健康应用)"]
        TH["SDKTestHelper<br/>(SDK 测试工程)"]
        AD["JLAudioUnitKitDemo<br/>(音频单元 Demo)"]
    end

    subgraph sg_Podfiles["依赖声明层 (Podfile)"]
        PF1["code/JL_Health/Podfile<br/>platform ios 12.0 · use_frameworks!"]
        PF2["code/SDKTestHelper/Podfile<br/>静态链接 · 未锁版本"]
    end

    subgraph sg_Pods["CocoaPods 解析与集成层"]
        CP["CocoaPods (pod install)<br/>生成 .xcworkspace + Pods 工程"]
        PODS["Pods 目录<br/>(已提交到仓库)"]
    end

    subgraph sg_Third["第三方框架层"]
        RX["RxSwift 6.6.0 / RxCocoa 6.6.0<br/>响应式编程"]
        SK["SnapKit 5.6.0<br/>Auto Layout DSL"]
        KF["Kingfisher 7.12.0<br/>图片加载缓存"]
        TS["Toast-Swift 5.0.1<br/>轻量提示"]
        FM["FMDB<br/>SQLite 封装"]
        SA["SwiftyAttributes 5.3.0<br/>富文本"]
        EXTRA["MJRefresh / WMZDialog / R.swift<br/>Starscream / Colours / JLUsefulTools"]
    end

    subgraph sg_Code["代码使用层"]
        EXPORT["@_exported import RxSwift/RxCocoa<br/>Kingfisher/SnapKit (BaseView.swift)"]
        LOCAL["普通 import (业务文件)"]
    end

    JL --> PF1
    TH --> PF2
    AD -.->|"CocoaPods 依赖<br/>见 Demo README"| CP
    PF1 --> CP
    PF2 --> CP
    CP --> PODS
    PODS --> RX
    PODS --> SK
    PODS --> KF
    PODS --> TS
    PODS --> FM
    PODS --> SA
    PODS --> EXTRA
    RX --> EXPORT
    KF --> EXPORT
    SK --> EXPORT
    TS --> LOCAL
    EXPORT --> LOCAL

架构要点说明:

  • 依赖声明与解析分离:各工程只维护一份 Podfile,pod install 时 CocoaPods 根据平台与 target 生成 Pods 工程。主工程显式开启 use_frameworks!(动态框架),测试工程将其注释掉(静态链接)。
  • Pods 目录入库:从 Grep 结果可以看到 code/JL_Health/Pods/ 下存在 RxCocoa、RxRelay 等源码,说明仓库将 CocoaPods 拉取的第三方源码一并提交,便于离线构建与版本一致性。
  • 全局导入降低样板代码:BaseView.swift 使用 @_exported import 一次性导出 RxSwift、RxCocoa、Kingfisher、SnapKit,使工程内所有文件无需重复 import 即可使用这些框架;SDKTestHelper/AppDelegate.swift 对 RxCocoa、RxSwift、SnapKit 采用相同策略。

主工程依赖清单(JieliJianKang)

code/JL_Health/Podfile 是整个仓库最核心的依赖声明文件,锁定 iOS 12.0 平台,启用动态框架,声明了 7 个 pod:

Source: code/JL_Health/Podfile

platform :ios, '12.0'

target 'JieliJianKang' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for JieliJianKang
  pod 'RxSwift','6.6.0'
  pod 'RxCocoa','6.6.0'
  pod 'SnapKit','5.6.0'
  pod 'Toast-Swift','5.0.1'
  pod 'Kingfisher','7.12.0'
  pod 'SwiftyAttributes','5.3.0'
  pod 'FMDB'

end

各依赖的用途

框架版本类型在工程中的用途使用证据
RxSwift6.6.0响应式编程事件流、序列处理、响应式绑定BaseView.swift 中 @_exported import RxSwift
RxCocoa6.6.0UIKit 响应式扩展控件事件绑定、Driver/Binder UI 绑定BaseView.swift 中 @_exported import RxCocoa
SnapKit5.6.0Auto Layout DSL链式约束布局BaseView.swift 中 @_exported import SnapKit
Toast-Swift5.0.1轻量提示弹出提示信息AlertVerifyCodeView.swift 中 import Toast_Swift
Kingfisher7.12.0图片加载/缓存网络图片异步加载、占位图BaseView.swift、DialSubCollectionViewCell.swift、AlertVerifyCodeView.swift 中 import Kingfisher
SwiftyAttributes5.3.0富文本链式创建 NSAttributedString(用于状态文案、表盘名称等)由 Podfile 声明
FMDB最新SQLite 封装本地数据持久化(基于 SQLite 的 OC 封装)由 Podfile 声明,未锁版本

设计意图说明:

  • 响应式 + 约束 + 图片加载是移动端标配组合。RxSwift/RxCocoa 负责把蓝牙 SDK 的异步回调(数据扫描、设备连接、健康数据上报)转换成可组合的 Observable 流;SnapKit 让复杂表盘/卡片 UI 的约束代码更短;Kingfisher 处理表盘图片与头像的网络加载与磁盘缓存。
  • 版本全部精确锁定(除 FMDB 外),这是主工程对可重复构建的强要求——健康类应用对稳定性敏感,不允许依赖漂移导致行为变化。
  • Toast-Swift 5.0.1 在主工程与测试工程中版本一致,说明它被当作"基础体验组件"在两个工程间保持同步。

SDKTestHelper 依赖清单

code/SDKTestHelper/Podfile 是 SDK 集成测试辅助工程的依赖声明,平台注释为 iOS 9.0(实际未生效),且 use_frameworks! 被注释掉,即采用静态链接方式集成:

Source: code/SDKTestHelper/Podfile

target 'SDKTestHelper' do
  # Comment the next line if you don't want to use dynamic frameworks
  #use_frameworks!

  # Pods for SDKTestHelper
  pod 'JLUsefulTools','0.0.2'
  pod 'RxSwift'
  pod 'RxCocoa'
  pod 'SnapKit'
  pod 'Colours'
  pod 'MJRefresh'
  pod 'WMZDialog'
  pod 'Toast-Swift','5.0.1'
  pod 'R.swift'
  pod 'FMDB'
  pod 'Starscream'

end
框架版本用途
JLUsefulTools0.0.2杰理自研的通用工具库(私有 pod),测试工程复用公司内部工具
RxSwift / RxCocoa最新与主工程相同的响应式基础
SnapKit最新约束布局
Colours最新颜色便捷工具(UIColor 扩展)
MJRefresh最新下拉刷新/上拉加载,用于列表调试页
WMZDialog最新通用弹窗组件,用于测试参数输入
Toast-Swift5.0.1提示(与主工程版本对齐)
R.swift最新资源类型安全访问(图片/颜色/字符串的强类型生成)
FMDB最新SQLite 封装
Starscream最新WebSocket 客户端,用于 SDK 与云端/调试通道的通信测试

设计意图说明:

  • 测试工程是内部工具,因此大多依赖不锁版本,跟随最新兼容版本即可;只有 Toast-Swift 因为跨工程使用习惯而锁定了 5.0.1。
  • JLUsefulTools 0.0.2 表明该仓库会消费杰理内部发布的私有 pod,这是公司内共享代码的标准做法。
  • 测试工程引入 R.swift,说明其 UI 代码通过资源强类型引用减少字符串硬编码。

JLAudioUnitKitDemo 依赖

code/JLAudioUnitKitDemo/README.md(以及 code/JLAudioUnitKitDemo/Code/README.md)明确说明了 Demo 工程同样使用 CocoaPods:

Source: code/JLAudioUnitKitDemo/README.md

工程使用了 Cocoapod 依赖:pod 'RxSwift' , pod 'RxCocoa', pod 'SnapKit', pod 'R.swift', pod 'Toast-Swift',
需要先安装 Cocoapod 并执行 pod install。

该 Demo 的依赖集合是"主工程基础三件套(RxSwift/RxCocoa/SnapKit)+ R.swift + Toast-Swift"的精简版,说明音频单元组件 Demo 只关心响应式 UI 与资源强类型,不引入图片加载等重依赖。

全局导入机制(@_exported import)

为了让整个 target 无需在每个文件重复写 import,工程采用 Swift 的 @_exported import 技巧。在 BaseView.swift 中一次性导出四个高频框架:

Sources:

  • code/JL_Health/JieliJianKang/Views/BaseView/BaseView.swift
  • code/SDKTestHelper/SDKTestHelper/AppDelegate.swift
// code/JL_Health/JieliJianKang/Views/BaseView/BaseView.swift
import UIKit
@_exported import RxSwift
@_exported import RxCocoa
@_exported import Kingfisher
@_exported import SnapKit
// code/SDKTestHelper/SDKTestHelper/AppDelegate.swift
@_exported import RxCocoa
@_exported import RxSwift
@_exported import SnapKit

工作机制与设计意图:

  • @_exported import 会把该模块的 import 关系传递给引用它的编译单元:只要某个文件(或 AppDelegate 所在的模块)编译时能看到这条语句,其所在 target 内其他源文件也可以直接使用这些框架,无需各自 import。
  • 主工程选择 BaseView.swift(视图基类文件)作为导出点,测试工程选择 AppDelegate.swift(应用入口),都是保证"每个编译单元都会直接或间接包含该文件"的位置。
  • 代价是隐式依赖:新开发者可能不清楚 RxSwift 从哪来,因此这些导出集中放在少数基类文件中,而不是散落各处,便于维护。

Usage Examples(实际代码摘录)

以下示例全部摘自仓库真实源码,展示第三方框架在工程中的引用方式。

基类文件全局导出(主工程)

BaseView.swift 是主工程所有视图的基类,同时充当第三方框架的全局导出点:

Source: code/JL_Health/JieliJianKang/Views/BaseView/BaseView.swift

import UIKit
@_exported import RxSwift
@_exported import RxCocoa
@_exported import Kingfisher
@_exported import SnapKit

在这之后,工程内任意业务文件(如列表 Cell、验证码弹窗)都不需要再写 import RxSwift 或 import SnapKit,直接使用 Observable、rx.、snp.makeConstraints 等 API。

业务文件中显式导入(组合使用)

部分业务文件仍会按需显式 import,例如表盘选择 Cell 同时使用 RxSwift 与 Kingfisher:

Source: code/JL_Health/JieliJianKang/Views/CellsView/DialSubCollectionViewCell.swift

import RxCocoa
import RxSwift
import Kingfisher

验证码弹窗视图则同时使用 Kingfisher(加载验证码图片)与 Toast-Swift(提示反馈):

Source: code/JL_Health/JieliJianKang/Views/VerifyCodeView/AlertVerifyCodeView.swift

import UIKit
import Kingfisher
import Toast_Swift

注意:Toast-Swift 的模块名为 Toast_Swift(下划线),与 pod 名 Toast-Swift(连字符)不同,import 时必须使用模块名。

测试工程入口全局导出

SDKTestHelper 的 AppDelegate.swift 在应用入口处导出 Rx 三件套:

Source: code/SDKTestHelper/SDKTestHelper/AppDelegate.swift

@_exported import RxCocoa
@_exported import RxSwift
@_exported import SnapKit

示例解读:以上摘录展示了两种并存的组织方式——"基类/入口集中导出 + 业务文件按需显式导入"。集中导出减少样板代码,显式导入则让依赖关系在局部代码中可见,两者互为补充。

Configuration Options(依赖配置项)

Podfile 中的关键配置项及其含义:

配置项主工程取值测试工程取值说明
platform :ios'12.0''9.0'(被注释,未生效)最低部署版本,决定可用 API 与框架兼容性
use_frameworks!启用注释掉(静态链接)是否将 pods 编译为动态 framework;静态链接可减小启动开销但可能引入符号冲突
pod '<name>','<version>'精确版本多数不锁版本版本锁定策略:主工程可重复构建,测试工程跟随最新
target '<Name>' do ... endJieliJianKangSDKTestHelper依赖作用域,只对指定 target 生效

Failure Modes、边界情况与一致性

  • 未安装 CocoaPods 时无法编译:所有工程依赖 pod install 生成的 .xcworkspace,直接从 .xcodeproj 编译会因缺少 Pods 集成而失败;Demo 工程 README 明确要求"先安装 Cocoapod 并执行 pod install"。
  • 模块名与 pod 名不一致:Toast-Swift 的 import 名是 Toast_Swift,写错会导致 "No such module" 编译错误,这是新手最容易踩的坑。
  • 动态框架 vs 静态链接的差异:主工程 use_frameworks! 开启,Pod 以 framework 形式链接;测试工程关闭,Pod 静态编译进主二进制。若在两个工程间复用代码,需注意 import 可见性与符号重复定义问题。
  • 版本漂移风险(测试工程):pod 'RxSwift' 不锁版本,每次 pod install 可能解析到新版本,导致测试工程行为与主工程(锁定 6.6.0)不一致——调试时若出现怪异现象,应优先检查 Podfile.lock 中的解析版本。
  • Pods 源码入库的双刃剑:仓库内包含 Pods/ 目录,优点是离线可编译、版本完全可控;缺点是升级依赖需同时提交大范围 diff,且需保持 Podfile.lock 与 Pods 目录同步。
  • RxRelay 等隐式依赖:Pods 工程中可见 RxRelay(RxCocoa 的依赖项)源码,说明 CocoaPods 会传递解析子依赖;业务代码可直接 import RxRelay 使用 BehaviorRelay/PublishRelay,但这属于未显式声明的传递依赖,升级 RxCocoa 时需留意。

性能与运维建议

  • 主工程锁定精确版本 + Pods 入库,已具备良好的可重复构建能力;CI 上建议直接使用 pod install --repo-update 并校验 Podfile.lock。
  • @_exported import 会让编译单元隐式依赖多个框架,增加模块依赖图复杂度,建议保持导出点集中(仅基类/入口),避免在多个文件重复导出。
  • 如需新增第三方框架,应先在对应工程的 Podfile 中声明,再执行 pod install,并同步提交 Podfile.lock 与 Pods/ 变更。

Extension Points(扩展方式)

  • 新增依赖:在目标工程的 Podfile 对应 target 块内追加 pod '<name>','<version>',然后 pod install。
  • 统一全局导出:新框架若需全工程使用,可在 BaseView.swift(主工程)或 AppDelegate.swift(测试工程)追加一行 @_exported import。
  • 私有 pod:JLUsefulTools 展示了私有 pod 的使用模式;公司内部组件可参照此方式发布到内部 Spec 仓库后以 pod 'JLXXX','x.y.z' 引入。

Related Links

  • 主工程 Podfile
  • SDKTestHelper Podfile
  • JLAudioUnitKitDemo README(依赖说明)
  • BaseView.swift(全局导出点)
  • DialSubCollectionViewCell.swift(RxSwift + Kingfisher 用法)
  • AlertVerifyCodeView.swift(Kingfisher + Toast-Swift 用法)
  • SDKTestHelper AppDelegate.swift(全局导出点)
Prev
在线文档与版本历史