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

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

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

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

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

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

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

SDKTestHelper 功能测试工具

SDKTestHelper 是仓库 code/SDKTestHelper/ 目录下的一个轻量级 iOS 测试工程(测试示例),用于在不运行完整「宜动健康」App 的情况下,快速验证 JL 健康 SDK 的各项功能与接口。

Purpose and Scope

本文档介绍 SDKTestHelper 测试工程的定位、启动流程、页面组织、工程依赖与可扩展点,帮助开发者快速上手该测试工具并理解其与主工程的关系。

本文档覆盖范围:

  • code/SDKTestHelper/ 工程的入口(AppDelegate)、主框架(MainTabBarViewController)与页面组织方式
  • 工程的第三方依赖(Pods)与 SDK 框架(XCFramework)集成方式
  • Swift/Objective-C 混编桥接(Bridging Header)
  • 与主工程 JL_Health 中测试辅助代码(UnitTester、JLTestGpsViewController)的关联

不属于本文档范围(由其他目录页覆盖):

  • 完整业务 App「宜动健康」的源码分析(code/JL_Health/,见「宜动健康 App」相关页面)
  • 核心 SDK 库(libs/ 下的 XCFramework)的内部实现
  • 音频编解码业务库示例(code/JLAudioUnitKitDemo/)

Overview

SDKTestHelper 是仓库 README 中标注的 「测试示例:简单功能测试源码」(code/SDKTestHelper/),与「完整示例:宜动健康应用源码」(code/JL_Health/)形成对照:主工程展示完整业务形态,而 SDKTestHelper 只聚焦于对 SDK 功能的快速验证,是 SDK 接入与调试阶段的轻量入口。

从工程结构可以看到它的核心设计意图:

  1. 极简入口:@main AppDelegate 直接以 UITabBarController 作为根控制器,没有复杂的业务导航栈,启动即进入测试页面。
  2. 按功能分页测试:主 TabBar 承载两个测试页面——「SDK」页(MainViewController,JL SDK 功能测试主页)与「iNRf」页(NRFViewController,NRF 相关功能模拟/测试页)。
  3. 直接依赖 SDK 与常用第三方库:通过 CocoaPods 集成 RxSwift/RxCocoa、SnapKit、Toast-Swift,并链接 JLLogHelper、JLBmpConvertKit 等 XCFramework,同时 @_exported import JLUsefulTools 使整个工程无需逐个 import 即可使用公共工具库。
  4. OC/Swift 混编:工程包含 SDKTestHelper-Bridging-Header.h 与 OCHelper.h,用于桥接既有 Objective-C 代码与测试辅助逻辑。
  5. 本地化就绪:通过 R.swift 生成资源(R.generated.swift),支持 en 与 zh-Hans 两种语言,字符串资源中包含 "JL SDK Test Helper" 等键值。

Architecture

下图展示 SDKTestHelper 的整体架构与依赖关系(节点名称均来自实际源码):

flowchart TD
    subgraph sg_App["SDKTestHelper App"]
        AppDelegate["AppDelegate (@main)"]
        MainTabBar["MainTabBarViewController (UITabBarController)"]
        NavVC["NavViewController"]
        MainVC["MainViewController (SDK 测试主页)"]
        NRFVC["NRFViewController (iNRf 测试页)"]
    end

    subgraph sg_Interop["OC/Swift 混编层"]
        BridgeHeader["SDKTestHelper-Bridging-Header.h"]
        OCHelper["OCHelper.h"]
    end

    subgraph sg_Pods["CocoaPods 依赖"]
        RxSwift["RxSwift / RxCocoa"]
        SnapKit["SnapKit"]
        Toast["Toast-Swift"]
    end

    subgraph sg_SDK["SDK 框架与工具库"]
        JLUsefulTools["JLUsefulTools (@_exported)"]
        JLLog["JLLogHelper.xcframework"]
        JLBmp["JLBmpConvertKit.xcframework"]
    end

    subgraph sg_Resources["资源与配置"]
        RSwift["R.generated.swift (R.swift)"]
        InfoPlist["Info.plist"]
        Entitlements["SDKTestHelper.entitlements"]
    end

    AppDelegate -->|"window.rootViewController"| MainTabBar
    MainTabBar -->|"Tab 0: SDK"| NavVC
    MainTabBar -->|"Tab 1: iNRf"| NRFVC
    NavVC --> MainVC
    MainVC --> OCHelper
    OCHelper --> BridgeHeader
    AppDelegate --> JLUsefulTools
    MainTabBar --> RSwift
    AppDelegate -->|"链接"| JLLog
    AppDelegate -->|"链接"| JLBmp
    MainVC --> RxSwift
    MainVC --> SnapKit
    MainVC --> Toast
    MainVC --> InfoPlist
    MainVC --> Entitlements

架构说明:

  • AppDelegate 是进程入口(@main),负责创建 UIWindow 并将 MainTabBarViewController 设为根控制器,同时完成 iOS 15 的 UITableView 外观适配与 R.swift 资源初始化(_R.initFold())。它还通过 @_exported import 将 JLUsefulTools、RxCocoa、RxSwift、SnapKit、Toast_Swift 全局导出,所有页面文件无需逐个 import 即可使用这些库。
  • MainTabBarViewController 是测试功能的一级导航容器:Tab 0「SDK」承载 MainViewController(JL SDK 功能测试主页),Tab 1「iNRf」承载 NRFViewController(NRF 功能测试页),两个页面均包裹在 NavViewController 中并隐藏导航栏,保证测试页面获得全屏空间。
  • OC/Swift 混编层:SDKTestHelper-Bridging-Header.h 与 OCHelper.h 为工程提供 Objective-C 能力桥接,测试页面可通过 OCHelper 调用 OC 侧逻辑。
  • 依赖层:Pods 提供响应式编程(RxSwift/RxCocoa)、自动布局(SnapKit)与轻提示(Toast-Swift);工程同时直接链接 JLLogHelper.xcframework(日志)与 JLBmpConvertKit.xcframework(BMP 转换)等 SDK 框架,用于验证对应功能。
  • 资源与配置:R.generated.swift 提供类型安全的资源访问(含 en / zh-Hans 本地化);Info.plist 与 SDKTestHelper.entitlements 定义运行配置与能力声明(工程中还存在 TestNetworkExtensionVC.swift,暗示网络扩展类功能的测试入口)。

主要实现分析

App 入口与启动流程(AppDelegate)

AppDelegate.swift 是整个测试工具的进程入口,其设计要点如下:

@_exported import JLUsefulTools
@_exported import RxCocoa
@_exported import RxSwift
@_exported import SnapKit
@_exported import Toast_Swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    static func getCurrentWindows() -> UIWindow? {
        let windows = UIApplication.shared.windows
        return windows.last
    }

    func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        let tabBar = MainTabBarViewController()
        if #available(iOS 15.0, *) {
            UITableView.appearance().sectionHeaderTopPadding = 0
        }
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = tabBar
        window?.makeKeyAndVisible()

        _R.initFold()
        return true
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        SoundInfoManager.share.addListen()
    }
}

Source: AppDelegate.swift

关键设计意图:

  • @_exported import 全局导出:这是本工程最典型的「测试工具」写法——因为所有测试页面都可能用到 RxSwift、SnapKit、Toast 与 JLUsefulTools,与其在每个页面重复 import,不如在 AppDelegate 一次性导出,降低测试页面的样板代码。代价是所有文件都被迫参与这些依赖的编译,但对测试工程而言收益远大于成本。
  • 直接以 TabBar 为根控制器:跳过登录、引导等业务流程,didFinishLaunching 中立刻构建 MainTabBarViewController 并设为 window.rootViewController,实现"打开即测"。
  • iOS 15 适配:UITableView.appearance().sectionHeaderTopPadding = 0 消除 iOS 15 引入的分组表头额外内边距,保证测试列表的紧凑展示。
  • _R.initFold():初始化 R.swift 资源运行时(对折叠/展开的资源结构做初始化),随后即可通过类型安全的 R.* 访问图片、字符串、本地化资源。
  • SoundInfoManager.share.addListen():进入前台时恢复声音相关监听(SDK 声音/提示功能的测试前置条件)。
  • getCurrentWindows():静态工具方法,返回 UIApplication.shared.windows 的最后一个窗口,供全局弹出提示(Toast、HUD)时定位展示层级。

TabBar 结构与测试页面组织(MainTabBarViewController)

MainTabBarViewController 是 UITabBarController 的子类,把整个测试工具划分为两大功能区:

private func setupTabs() {
    let mainVC = MainViewController()
    mainVC.tabBarItem = UITabBarItem(title: "SDK", image: UIImage(systemName: "list.bullet"), tag: 0)
    let mainNavc = NavViewController(rootViewController: mainVC)
    mainNavc.setNavigationBarHidden(true, animated: false)

    let nrfVC = NRFViewController()
    nrfVC.tabBarItem = UITabBarItem(title: "iNRf", image: UIImage(systemName: "antenna.radiowaves.left.and.right"), tag: 1)
    let nrfNavc = NavViewController(rootViewController: nrfVC)
    nrfNavc.setNavigationBarHidden(true, animated: false)
    viewControllers = [mainNavc, nrfNavc]
}

Source: MainTabBarViewController.swift

设计意图:

  • 两个 Tab 职责分离:「SDK」页(MainViewController)是 JL SDK 各功能(设备连接、健康数据、音频等)的集中测试入口;「iNRf」页(NRFViewController)承载 NRF(Nordic 无线协议)相关模拟/测试页面,图标 antenna.radiowaves.left.and.right 也暗示其无线射频测试定位。
  • 统一包一层 NavViewController 并隐藏导航栏:既保留 UINavigationController 的页面 push/pop 能力,又隐藏系统导航栏,让测试页面用自定义 UI 展示,与主工程风格保持一致。
  • 外观定制:configureTabBarAppearance() 使用 UITabBarAppearance 统一普通态(darkGray)与选中态(systemBlue)的图标与标题颜色,提升测试工具自身的可用性。

工程结构与依赖

根据 SDKTestHelper.xcodeproj/project.pbxproj 与 Podfile,工程的关键组成如下:

组成文件/框架作用
应用入口AppDelegate.swift、MainTabBarViewController.swift、MainViewController.swift启动与测试页面
OC 混编SDKTestHelper-Bridging-Header.h、OCHelper.hSwift 调用 Objective-C 逻辑
测试页面TestNetworkExtensionVC.swift、JLAudioSessionManager.swift、NRFViewController 等网络扩展、音频会话等专项测试
SDK 框架JLLogHelper.xcframework、JLBmpConvertKit.xcframework日志、BMP 转换等 SDK 能力
CocoaPodsPods 工程(target 'SDKTestHelper',含 RxSwift 等)第三方依赖
配置Info.plist、SDKTestHelper.entitlements运行配置与能力声明

Sources:

  • project.pbxproj
  • Podfile

其中 Pods-SDKTestHelper.xcscheme(位于 code/SDKTestHelper/Pods/Pods.xcodeproj/)表明 Pods 以独立工程方式管理,libPods-SDKTestHelper.a 以静态库形式链接进测试 App。

Swift/Objective-C 混编

工程同时维护了 SDKTestHelper-Bridging-Header.h 与 OCHelper.h:前者是 Xcode 的 Swift-OC 桥接头,使 Swift 代码能直接使用 OC 类;后者提供面向测试场景的 OC 辅助接口。这种设计是为了复用 SDK 生态中既有的 OC 实现(例如老版本的测试逻辑、C 风格工具函数),避免在 Swift 中重写,同时把 OC 暴露面收敛到 OCHelper 一个文件中,便于维护。

与主工程的测试辅助代码关联

仓库中与「功能测试」直接相关的代码并不只存在于 SDKTestHelper:

  • code/JL_Health/JieliJianKang/UnitTester/(DataTester.swift、OCTest.h/m、test.jpg):宜动健康 App 内置的数据测试器,通过 OC 桥接执行测试用例,可视为 SDKTestHelper 在完整 App 内的对等物。
  • code/JL_Health/JieliJianKang/运动界面/CustomView/JLGPSView/JLTestGpsViewController.*:GPS 数据测试页面,展示主工程中运动模块的测试方式。

这两处为需要「在完整业务环境里验证 SDK」的场景提供了参考实现;而 SDKTestHelper 则面向「脱离业务、快速验证 SDK 接口」的场景,两者互补。

本地化与资源

R.generated.swift(R.swift 生成产物)声明了本地化键 jlsdkTestHelper(key: "JL SDK Test Helper",developmentValue 同),支持 en 与 zh-Hans 两个 locale,说明测试工具自身的文案已做国际化处理,便于团队内部多语言使用。

核心流程:App 启动到测试页面呈现

sequenceDiagram
    participant OS as iOS 系统
    participant AD as AppDelegate (@main)
    participant R as R.swift 资源
    participant TB as MainTabBarViewController
    participant MC as MainViewController (SDK 页)
    participant NC as NavViewController
    participant NR as NRFViewController (iNRf 页)

    OS->>AD: application(_:didFinishLaunchingWithOptions:)
    activate AD
    AD->>AD: @_exported import 各依赖库
    AD->>AD: UITableView 外观适配 (iOS 15)
    AD->>TB: 创建 MainTabBarViewController
    AD->>TB: 设为 window.rootViewController
    AD->>R: _R.initFold() 初始化资源
    AD-->>OS: return true
    deactivate AD

    TB->>TB: setupTabs() 构建两个 Tab
    TB->>MC: 创建 MainViewController (tab 0 "SDK")
    MC->>NC: 包裹进 NavViewController,隐藏导航栏
    TB->>NR: 创建 NRFViewController (tab 1 "iNRf")
    NR->>NC: 包裹进 NavViewController,隐藏导航栏
    TB->>TB: viewControllers = [mainNavc, nrfNavc]
    Note over MC,NR: 用户切换 Tab 进入对应测试页<br/>测试页通过 OCHelper 桥接 OC 逻辑<br/>并调用 JLLogHelper / JLBmpConvertKit 等 SDK 验证功能

    OS->>AD: applicationWillEnterForeground
    AD->>AD: SoundInfoManager.share.addListen() 恢复声音监听

流程要点:

  1. 启动:iOS 调用 AppDelegate.application(_:didFinishLaunchingWithOptions:),此时 @_exported import 已使全工程可用公共依赖。
  2. 根控制器装配:创建 MainTabBarViewController 并赋值给 UIWindow.rootViewController,随后 makeKeyAndVisible() 展示首帧;iOS 15 下先消除 UITableView 表头内边距。
  3. 资源初始化:_R.initFold() 完成 R.swift 资源折叠初始化,保证后续 R.* 访问安全。
  4. Tab 装配:MainTabBarViewController.setupTabs() 创建「SDK」「iNRf」两个 Tab,各自包裹 NavViewController 并隐藏导航栏。
  5. 测试执行:用户进入对应测试页,页面通过 Bridging Header/OCHelper 调用 OC 逻辑,并直接调用链接的 SDK 框架(日志、BMP 转换等)验证功能。
  6. 前后台切换:进入前台时恢复 SoundInfoManager 的声音监听,保证声音类测试可用。

Usage Examples

示例 1:全局导出依赖(AppDelegate)

测试工具通过 @_exported import 让所有页面免于重复 import:

@_exported import JLUsefulTools
@_exported import RxCocoa
@_exported import RxSwift
@_exported import SnapKit
@_exported import Toast_Swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    static func getCurrentWindows() -> UIWindow? {
        let windows = UIApplication.shared.windows
        return windows.last
    }

Source: AppDelegate.swift

说明:JLUsefulTools、RxSwift、SnapKit、Toast_Swift 被全局导出后,任何测试页面都可以直接使用 Observable、snap.makeConstraints、view.makeToast 等能力,无需逐个 import——这是为测试代码追求极简样板的设计选择。

示例 2:根控制器装配与资源初始化

let tabBar = MainTabBarViewController()
if #available(iOS 15.0, *) {
    UITableView.appearance().sectionHeaderTopPadding = 0
}
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = tabBar
window?.makeKeyAndVisible()

_R.initFold()

Source: AppDelegate.swift

说明:window 使用全屏 bounds 创建,直接以 TabBar 为根;_R.initFold() 必须在使用任何 R.* 资源之前调用,保证本地化字符串与图片资源的内部结构已初始化。

示例 3:测试页面 Tab 注册(MainTabBarViewController)

private func setupTabs() {
    let mainVC = MainViewController()
    mainVC.tabBarItem = UITabBarItem(title: "SDK", image: UIImage(systemName: "list.bullet"), tag: 0)
    let mainNavc = NavViewController(rootViewController: mainVC)
    mainNavc.setNavigationBarHidden(true, animated: false)

    let nrfVC = NRFViewController()
    nrfVC.tabBarItem = UITabBarItem(title: "iNRf", image: UIImage(systemName: "antenna.radiowaves.left.and.right"), tag: 1)
    let nrfNavc = NavViewController(rootViewController: nrfVC)
    nrfNavc.setNavigationBarHidden(true, animated: false)
    viewControllers = [mainNavc, nrfNavc]
}

Source: MainTabBarViewController.swift

说明:新增测试功能区时,只需在 setupTabs() 中仿照上述模式追加 UITabBarItem 并设置 viewControllers 数组即可;隐藏导航栏保证测试页自定义 UI 不被系统栏挤压。

示例 4:测试页面外观定制

private func configureTabBarAppearance() {
    let appearance = UITabBarAppearance()
    let normalTitleAttr: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.darkGray]
    let selectedTitleAttr: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.systemBlue]
    appearance.stackedLayoutAppearance.normal.iconColor = .darkGray
    appearance.stackedLayoutAppearance.selected.iconColor = .systemBlue
    appearance.stackedLayoutAppearance.normal.titleTextAttributes = normalTitleAttr
    appearance.stackedLayoutAppearance.selected.titleTextAttributes = selectedTitleAttr
    tabBar.standardAppearance = appearance
    tabBar.tintColor = .systemBlue
    tabBar.unselectedItemTintColor = .darkGray
}

Source: MainTabBarViewController.swift

说明:使用 UITabBarAppearance(而非直接改 tintColor)是为了覆盖 iOS 13+ 的层级外观,普通态 darkGray、选中态 systemBlue 的对比让测试工具的 Tab 状态一目了然。

Configuration Options

SDKTestHelper 的配置分散在工程文件、Info.plist、entitlements 与代码常量中。以下为已验证的配置项:

配置项类型默认值说明
Info.plistplist工程自带App 基础运行配置(Bundle 标识、启动屏、权限声明等),由 Xcode 工程管理
SDKTestHelper.entitlementsentitlements工程自带能力声明文件,配合 TestNetworkExtensionVC.swift 用于网络扩展类功能的测试授权
UITableView.sectionHeaderTopPaddingCGFloat0(iOS 15+)通过 UITableView.appearance() 全局设置,消除分组表头多余内边距
Tab 数量与顺序代码["SDK", "iNRf"]由 MainTabBarViewController.setupTabs() 硬编码,新增测试区需改代码
导航栏显隐BoolhiddenNavViewController.setNavigationBarHidden(true),测试页自定义 UI
本地化语言资源en / zh-Hans由 R.generated.swift 声明的 Localizable 表提供,键 jlsdkTestHelper
Pods 依赖Podfiletarget 'SDKTestHelper'RxSwift、RxCocoa、SnapKit、Toast-Swift 等,静态库 libPods-SDKTestHelper.a

Sources:

  • project.pbxproj
  • Podfile

说明:Info.plist 与 SDKTestHelper.entitlements 的具体键值未在本页验证范围内读取;上表仅记录其在工程中的存在性与用途。若需修改权限声明或网络扩展授权,请直接编辑这两个文件。

API Reference

以下为 SDKTestHelper 核心类型对外暴露的主要接口(基于已读取源码):

AppDelegate

static func getCurrentWindows() -> UIWindow?

返回 UIApplication.shared.windows 的最后一个窗口,用于在测试页面中定位全局弹层(Toast/HUD)的展示容器。

  • 参数:无
  • 返回值:UIWindow?,当前应用窗口数组的最后一个元素;无窗口时返回 nil
  • 设计意图:多窗口/多场景环境下,windows.last 通常是最近激活的窗口,适合作为提示浮层挂载点

func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool

应用启动回调,负责装配根控制器与初始化资源。

  • 参数:application(UIApplication)、launchOptions(启动选项字典)
  • 返回值:Bool,始终返回 true
  • 行为:构建 MainTabBarViewController → 设置 window.rootViewController → makeKeyAndVisible() → _R.initFold()

func applicationWillEnterForeground(_ application: UIApplication)

进入前台回调,调用 SoundInfoManager.share.addListen() 恢复声音监听。

MainTabBarViewController

class MainTabBarViewController: UITabBarController

主入口 TabBar 控制器,承载 JLSDK 测试主页面与 NRF 模拟页面。

private func setupTabs()

构建两个 Tab:「SDK」→ MainViewController;「iNRf」→ NRFViewController,均包裹 NavViewController 并隐藏导航栏。

  • 无参数、无返回值
  • 内部逻辑:创建两个 UITabBarItem(SF Symbols 图标 list.bullet / antenna.radiowaves.left.and.right),组装 viewControllers 数组

private func configureTabBarAppearance()

配置 UITabBarAppearance:普通态 darkGray、选中态 systemBlue,并同步设置 tintColor 与 unselectedItemTintColor。

Failure Modes, Edge Cases & Concurrency

基于已读取源码,SDKTestHelper 中可识别的边界情况与潜在风险如下:

  • windows.last 可能为 nil 或非关键窗口:getCurrentWindows() 直接返回 UIApplication.shared.windows 的最后一个元素。多窗口(如 iPad 分屏、外接显示器)场景下,last 不一定是主窗口;无窗口时返回 nil,调用方需自行判空,否则强制解包会崩溃。
  • _R.initFold() 调用时机:必须在任何 R.* 资源访问前调用。若后续新增测试页面并在初始化前访问资源,R.swift 运行时可能因资源结构未初始化而返回异常结果。当前实现将其放在 didFinishLaunching 末尾,处于安全位置。
  • iOS 版本差异:UITableView.appearance().sectionHeaderTopPadding = 0 仅对 iOS 15+ 生效(#available 保护)。若测试页面依赖不同 iOS 版本的表头布局,需按版本区分适配。
  • 前台监听恢复:SoundInfoManager.share.addListen() 只在 applicationWillEnterForeground 调用,若后台期间 SDK 声音状态异常,恢复时机可能影响声音测试的即时性。
  • 混编层可见性:@_exported import 使依赖全局可见,但也意味着任何测试文件都能访问这些库;若引入同名符号,可能造成编译期歧义,新增依赖时需留意符号冲突。
  • Tab 配置为硬编码:Tab 数量、标题、图标均在 setupTabs() 内写死,运行时无动态增删能力;并发/多线程方面本工程未发现共享可变状态,测试页面各自独立。

Performance & Operational Considerations

  • 启动即全量依赖:@_exported import 与静态库链接(libPods-SDKTestHelper.a、各 XCFramework)使启动阶段加载较多符号,但测试工程对启动耗时不敏感,属于可接受的权衡。
  • 测试页内存:Tab 容器默认会保留各 Tab 的视图控制器,长时间运行多个测试页时内存占用会累积;测试完成后建议及时返回或重启 App 释放资源。
  • 资源本地化:R.generated.swift 为类型安全资源访问,可避免字符串硬编码带来的拼写错误;新增文案时需同步更新 Localizable 表(en / zh-Hans)。
  • 操作建议:在真机上运行以验证蓝牙/声音/网络等硬件相关 SDK 功能;SDKTestHelper.entitlements 若包含网络扩展能力,需在签名与描述文件中保持一致,否则相关测试页(如 TestNetworkExtensionVC)可能因授权失败无法启动。

Extension Points

SDKTestHelper 作为功能测试工具,扩展测试项的方式非常直接:

  1. 新增测试页面:在 MainTabBarViewController.setupTabs() 中仿照现有模式创建新的 UITabBarItem 并追加到 viewControllers,即可获得独立的测试分区;或直接在 MainViewController 的测试列表中加入新的功能入口。
  2. 复用 OC 测试逻辑:在 OCHelper.h(配合 SDKTestHelper-Bridging-Header.h)中暴露新的 OC 方法,Swift 测试页即可调用既有 OC 实现,避免重写。
  3. 接入更多 SDK 框架:在 Xcode 工程的 Frameworks 阶段链接新的 XCFramework(如现有 JLLogHelper、JLBmpConvertKit 的挂法),并在对应测试页中调用其接口验证功能。
  4. 新增本地化文案:在 Localizable.strings(en / zh-Hans)中补充键值,R.generated.swift 会生成类型安全访问器(如 R.string.localizable.jlsdkTestHelper)。
  5. 对照主工程测试代码:code/JL_Health/JieliJianKang/UnitTester/(DataTester.swift、OCTest.h/m)与 JLTestGpsViewController 展示了在完整业务环境中的测试写法,可作为扩展 SDKTestHelper 功能的参考蓝本。

Related Links

  • README.md — 工程目录说明(code/SDKTestHelper/ 定位为「简单功能测试源码」)
  • AppDelegate.swift — 应用入口与全局依赖导出
  • MainTabBarViewController.swift — 测试功能 Tab 容器
  • SDKTestHelper.xcodeproj/project.pbxproj — 工程文件与框架链接
  • SDKTestHelper/Podfile — CocoaPods 依赖声明
  • UnitTester(主工程测试辅助) — 宜动健康内置数据测试器
  • JLTestGpsViewController — 主工程 GPS 测试页面

兄弟页面指引:完整业务 App 的源码分析见「宜动健康」相关目录页;核心 SDK 库说明见 libs/ 对应页面;音频编解码示例见 JLAudioUnitKitDemo 页面。

Next
音频编解码示例工程