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 接入与调试阶段的轻量入口。
从工程结构可以看到它的核心设计意图:
- 极简入口:
@main AppDelegate直接以UITabBarController作为根控制器,没有复杂的业务导航栈,启动即进入测试页面。 - 按功能分页测试:主 TabBar 承载两个测试页面——「SDK」页(
MainViewController,JL SDK 功能测试主页)与「iNRf」页(NRFViewController,NRF 相关功能模拟/测试页)。 - 直接依赖 SDK 与常用第三方库:通过 CocoaPods 集成
RxSwift/RxCocoa、SnapKit、Toast-Swift,并链接JLLogHelper、JLBmpConvertKit等 XCFramework,同时@_exported import JLUsefulTools使整个工程无需逐个 import 即可使用公共工具库。 - OC/Swift 混编:工程包含
SDKTestHelper-Bridging-Header.h与OCHelper.h,用于桥接既有 Objective-C 代码与测试辅助逻辑。 - 本地化就绪:通过 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.h | Swift 调用 Objective-C 逻辑 |
| 测试页面 | TestNetworkExtensionVC.swift、JLAudioSessionManager.swift、NRFViewController 等 | 网络扩展、音频会话等专项测试 |
| SDK 框架 | JLLogHelper.xcframework、JLBmpConvertKit.xcframework | 日志、BMP 转换等 SDK 能力 |
| CocoaPods | Pods 工程(target 'SDKTestHelper',含 RxSwift 等) | 第三方依赖 |
| 配置 | Info.plist、SDKTestHelper.entitlements | 运行配置与能力声明 |
Sources:
其中 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() 恢复声音监听
流程要点:
- 启动:iOS 调用
AppDelegate.application(_:didFinishLaunchingWithOptions:),此时@_exported import已使全工程可用公共依赖。 - 根控制器装配:创建
MainTabBarViewController并赋值给UIWindow.rootViewController,随后makeKeyAndVisible()展示首帧;iOS 15 下先消除UITableView表头内边距。 - 资源初始化:
_R.initFold()完成 R.swift 资源折叠初始化,保证后续R.*访问安全。 - Tab 装配:
MainTabBarViewController.setupTabs()创建「SDK」「iNRf」两个 Tab,各自包裹NavViewController并隐藏导航栏。 - 测试执行:用户进入对应测试页,页面通过 Bridging Header/
OCHelper调用 OC 逻辑,并直接调用链接的 SDK 框架(日志、BMP 转换等)验证功能。 - 前后台切换:进入前台时恢复
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.plist | plist | 工程自带 | App 基础运行配置(Bundle 标识、启动屏、权限声明等),由 Xcode 工程管理 |
SDKTestHelper.entitlements | entitlements | 工程自带 | 能力声明文件,配合 TestNetworkExtensionVC.swift 用于网络扩展类功能的测试授权 |
UITableView.sectionHeaderTopPadding | CGFloat | 0(iOS 15+) | 通过 UITableView.appearance() 全局设置,消除分组表头多余内边距 |
| Tab 数量与顺序 | 代码 | ["SDK", "iNRf"] | 由 MainTabBarViewController.setupTabs() 硬编码,新增测试区需改代码 |
| 导航栏显隐 | Bool | hidden | NavViewController.setNavigationBarHidden(true),测试页自定义 UI |
| 本地化语言 | 资源 | en / zh-Hans | 由 R.generated.swift 声明的 Localizable 表提供,键 jlsdkTestHelper |
| Pods 依赖 | Podfile | target 'SDKTestHelper' | RxSwift、RxCocoa、SnapKit、Toast-Swift 等,静态库 libPods-SDKTestHelper.a |
Sources:
说明:
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 作为功能测试工具,扩展测试项的方式非常直接:
- 新增测试页面:在
MainTabBarViewController.setupTabs()中仿照现有模式创建新的UITabBarItem并追加到viewControllers,即可获得独立的测试分区;或直接在MainViewController的测试列表中加入新的功能入口。 - 复用 OC 测试逻辑:在
OCHelper.h(配合SDKTestHelper-Bridging-Header.h)中暴露新的 OC 方法,Swift 测试页即可调用既有 OC 实现,避免重写。 - 接入更多 SDK 框架:在 Xcode 工程的 Frameworks 阶段链接新的 XCFramework(如现有
JLLogHelper、JLBmpConvertKit的挂法),并在对应测试页中调用其接口验证功能。 - 新增本地化文案:在
Localizable.strings(en / zh-Hans)中补充键值,R.generated.swift会生成类型安全访问器(如R.string.localizable.jlsdkTestHelper)。 - 对照主工程测试代码:
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页面。