环境要求与工程导入
本文档介绍 iOS-BT-Demo 仓库(杰理蓝牙产品 iOS 端测试示例代码集合)的运行环境要求、工程结构以及从克隆仓库到在 Xcode 中成功导入并运行的完整流程。
Purpose and Scope
本页面向希望在本机搭建杰理 iOS 蓝牙测试环境的开发者,涵盖:
- 开发与运行环境的最低要求(iOS 版本、Xcode 版本、开发语言)
- 支持的蓝牙协议与适用设备
- 仓库顶层工程结构
- 从
git clone到 Xcode 导入、编译运行的完整步骤 - 蓝牙权限声明(
Info.plist)与构建配置(.xcconfig)说明 - 常见环境问题与故障排查
以下主题由同仓库其他页面/文档单独介绍,不在本页展开:示例工程内部的连接事件监听、服务发现、数据收发等运行时逻辑(见 UsingCoreBluetoothClassic 示例说明页);版本历史与许可证(见根目录 README)。本页只聚焦“环境准备 + 导入工程”这一环节。
Overview
iOS-BT-Demo 是珠海杰理科技股份有限公司为蓝牙产品提供的 iOS 端测试示例代码集合仓库,当前包含一个核心用例:GATT Over BR/EDR 连接示例(UsingCoreBluetoothClassic/),演示如何在 iOS 端通过 GATT 协议与杰理蓝牙产品进行高速数据通讯。
由于 iOS 平台的封闭性,示例工程对系统版本、开发工具版本有明确的下限要求:
- 示例使用了
CBCentralManager.registerForConnectionEvents(options:)这一 API,该 API 仅在 iOS 13.0 及以上版本可用,因此最低系统版本被锁定为 iOS 13.0。 - 工程以 Swift 编写,需要 Xcode 14.0+ 以支持相应的 SDK 与构建工具链。
- 从 iOS 13 开始,访问蓝牙必须获得用户明确授权,因此
Info.plist中必须声明NSBluetoothAlwaysUsageDescription。
理解这些约束,是顺利完成工程导入、避免“编译通过但运行时无响应”类问题的前提。
Architecture
下图展示了从环境准备、仓库获取到工程导入、构建运行,最终与蓝牙设备交互的整体架构与数据通路:
flowchart TD
subgraph sg_Env["环境要求层"]
iOS["iOS 13.0+(最低)<br/>目标 iOS 16+"]
Xcode["Xcode 14.0+"]
Lang["Swift / Objective-C"]
end
subgraph sg_Repo["仓库层"]
Root["ios-bt-demo/(根仓库)"]
Sub["UsingCoreBluetoothClassic/(示例工程)"]
Root -->|"git clone"| Sub
end
subgraph sg_Import["工程导入层"]
Xcodeproj["CoreBluetoothClassicSample.xcodeproj"]
Xcconfig["Configuration/SampleCode.xcconfig<br/>SAMPLE_CODE_DISAMBIGUATOR"]
Plist["Info.plist<br/>NSBluetoothAlwaysUsageDescription"]
Xcodeproj --> Xcconfig
Xcodeproj --> Plist
end
subgraph sg_Runtime["运行时层"]
CBCM["CBCentralManager"]
CBEvent["registerForConnectionEvents(options:)"]
Device["杰理蓝牙产品(BR/EDR)"]
end
Xcode --> Xcodeproj
Sub --> Xcodeproj
Plist -->|"蓝牙权限授权"| CBCM
CBCM --> CBEvent
CBEvent --> Device
iOS --> CBCM
各层职责说明:
- 环境要求层:决定了示例能否编译与运行。
registerForConnectionEvents是 iOS 13.0 新增 API,低于该版本的系统无法调用,故最低版本定为 iOS 13.0;Xcode 14.0+ 提供所需的 Swift 工具链与 iOS SDK。 - 仓库层:
ios-bt-demo为顶层仓库,UsingCoreBluetoothClassic是当前唯一的示例工程子目录,二者通过git clone一次性获取。 - 工程导入层:Xcode 打开
.xcodeproj后,会读取SampleCode.xcconfig参与构建配置(用于根据开发团队生成唯一 Bundle ID),并在运行时读取Info.plist中的蓝牙权限声明。 - 运行时层:权限通过后,
CBCentralManager初始化并注册 GATT over BR/EDR 连接事件,最终与杰理蓝牙设备建立通讯。
该结构说明:本页关注前三层(环境、仓库、导入),运行时层的逻辑细节由示例工程页面另行深入介绍。
环境要求
系统与工具要求
根目录 README.md 与示例工程 UsingCoreBluetoothClassic/README.md 分别给出了仓库级与工程级的环境要求,汇总如下:
| 项目 | 仓库级要求 | 示例工程(UsingCoreBluetoothClassic)要求 |
|---|---|---|
| 最低 iOS 版本 | iOS 13.0 | iOS 13.0 |
| 目标 iOS 版本 | iOS 16+ | iOS 13.0+ |
| 开发语言 | Swift / Objective-C | Swift |
| 开发环境 | —(隐含 Xcode) | Xcode 14.0+ |
设计意图: 两个文档的版本下限一致(iOS 13.0),因为核心 API registerForConnectionEvents(options:) 自 iOS 13.0 起才可用。仓库级 README 将目标版本写为 iOS 16+,反映当前示例的验证基线,但实际最低兼容性仍以 iOS 13.0 为准。
支持的蓝牙协议与设备
| 协议 | 说明 | 状态 |
|---|---|---|
| GATT over BR/EDR | 基于经典蓝牙(BR/EDR 底层协议)的 GATT 通讯,传输速率更高、数据量更大 | ✅ 支持 |
适用场景:双模蓝牙设备(同时支持经典蓝牙与 BLE),需要通过 GATT 协议进行高速数据通讯。iOS 端对 GATT over BR/EDR 的支持依赖 iOS 13+,官方建议在目标设备上进行充分测试。
注意:iOS 对 GATT over BLE(低功耗蓝牙)与 GATT over BR/EDR(经典蓝牙)的实现路径不同;本示例专用于 BR/EDR 场景。
工程结构
导入前先了解仓库布局,便于确认选择正确的工程目录:
ios-bt-demo/
├── UsingCoreBluetoothClassic/ # 📌 ATT 设备连接示例(GATT over BR/EDR)
│ ├── CoreBluetoothClassicSample.xcodeproj/ # Xcode 工程文件(导入入口)
│ ├── CoreBluetoothClassicSample/ # 应用主模块
│ │ ├── AppDelegate.swift # 应用代理
│ │ ├── CentralViewController.swift # 中心设备控制器(扫描与连接)
│ │ ├── PeripheralViewController.swift # 外设交互控制器(数据收发)
│ │ ├── Assets.xcassets/ # 资源文件
│ │ ├── Base.lproj/ # Storyboard 文件
│ │ └── Info.plist # 应用配置(权限等)
│ ├── Configuration/
│ │ └── SampleCode.xcconfig # 构建配置
│ └── LICENSE # Apache 2.0 开源协议
├── LICENSE.txt # Apache 2.0 开源协议
└── README.md
导入时选择 CoreBluetoothClassicSample.xcodeproj 而不是仓库根目录,因为后者仅是文档与示例的容器。
工程导入步骤
1. 克隆仓库
git clone https://github.com/Jieli-Tech/ios-bt-demo.git
cd ios-bt-demo
如需直接进入示例工程目录:
cd ios-bt-demo/UsingCoreBluetoothClassic
说明:仓库托管在 GitHub(Jieli-Tech/ios-bt-demo),也可通过 Gitee 镜像地址
https://gitee.com/Jieli-Tech/ios-bt-demo.git克隆。若本地已有仓库,可省略本步骤直接打开工程。
2. 在 Xcode 中导入并运行
- 打开 Xcode(要求 14.0+)
- 点击 File → Open,选择示例目录下的
CoreBluetoothClassicSample.xcodeproj - 等待工程加载完成(Xcode 会自动解析工程引用、资源与配置)
- 选择目标 iOS 设备(真机)或模拟器
- 点击 Product → Run(▶) 编译并运行
- 在设备上打开 APP,首次启动时授权蓝牙权限,即可测试蓝牙功能
设计意图: 工程使用 .xcodeproj 标准格式,无需 pod install 或 Swift Package Manager 等额外依赖管理步骤——示例不依赖任何第三方库,所有功能基于系统框架 CoreBluetooth 实现,因此导入路径最简。
3. 权限配置
从 iOS 13 开始,访问蓝牙需要用户的明确同意。示例已在 Info.plist 中预置了权限描述:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Use bluetooth to discover, connect to, and share information with nearby devices</string>
如需后台蓝牙支持,还需在 Info.plist 中配置后台模式:
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
</array>
实际使用时建议将描述文案替换为符合自己应用场景的中文说明,否则 App Store 审核与用户授权弹窗会展示默认英文文案。
核心流程
以下时序图展示了从克隆仓库到运行并与蓝牙设备建立连接的完整生命周期:
sequenceDiagram
participant Dev as 开发者
participant Git as 代码仓库
participant XC as Xcode 14.0+
participant App as 示例 App(iOS 13.0+)
participant BT as 系统蓝牙/CoreBluetooth
participant D as 杰理蓝牙设备
Dev->>Git: git clone ios-bt-demo
Git-->>Dev: 仓库文件(含 .xcodeproj / Info.plist)
Dev->>XC: File → Open CoreBluetoothClassicSample.xcodeproj
XC->>XC: 读取 SampleCode.xcconfig、解析资源
Dev->>XC: Product → Run(选择真机/模拟器)
XC->>App: 编译并安装
App->>BT: 初始化 CBCentralManager
BT->>App: 弹出蓝牙权限授权请求
Dev->>BT: 授权 NSBluetoothAlwaysUsageDescription
App->>BT: registerForConnectionEvents(options:)
BT->>D: 监听 GATT over BR/EDR 连接事件
D-->>BT: peerConnected / peerDisconnected
BT-->>App: centralManager(_:connectionEventDidOccur:for:)
关键节点说明:
- 导入:Xcode 打开
.xcodeproj后即完成工程解析;SampleCode.xcconfig中SAMPLE_CODE_DISAMBIGUATOR会基于开发团队(DEVELOPMENT_TEAM)派生唯一 Bundle ID,避免多人共用示例时签名冲突。 - 权限:首次运行
CBCentralManager初始化会触发系统权限弹窗;若用户拒绝,centralManagerDidUpdateState(_:)中不会进入.poweredOn分支,连接事件监听无法注册。 - 连接事件:系统在 BR/EDR 设备连接/断开时回调
centralManager(_:connectionEventDidOccur:for:),示例据此维护外设列表。
配置选项
SampleCode.xcconfig
示例工程通过 SampleCode.xcconfig 注入构建配置:
// SampleCode.xcconfig
SAMPLE_CODE_DISAMBIGUATOR=${DEVELOPMENT_TEAM}
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
SAMPLE_CODE_DISAMBIGUATOR | 构建变量 | ${DEVELOPMENT_TEAM} | 用于派生唯一 Bundle Identifier;在 Xcode 中设置开发团队后生效 |
设计意图:示例工程经常被下载且未预设开发团队,直接使用固定 Bundle ID 会导致多用户签名冲突。该变量让 Bundle ID 随
DEVELOPMENT_TEAM变化。官方注释明确提示:不要在自己的正式项目中采用此做法,它仅适用于示例代码工程。
Info.plist 权限键
| 键 | 类型 | 默认值(示例) | 说明 |
|---|---|---|---|
NSBluetoothAlwaysUsageDescription | String | "Use bluetooth to discover, connect to, and share information with nearby devices" | 蓝牙使用权限描述,iOS 13+ 必需 |
UIBackgroundModes | Array<String> | bluetooth-central(按需) | 后台蓝牙模式,仅在需要后台扫描/连接时配置 |
使用示例
示例 1:克隆并进入示例工程
git clone https://github.com/Jieli-Tech/ios-bt-demo.git
cd ios-bt-demo/UsingCoreBluetoothClassic
Source: README.md
示例 2:蓝牙权限声明(Info.plist)
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Use bluetooth to discover, connect to, and share information with nearby devices</string>
如需后台蓝牙支持,还需配置后台模式:
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
</array>
示例 3:初始化中央管理器并注册连接事件(验证环境是否就绪)
导入成功后,CentralViewController 中通过以下代码验证蓝牙环境:仅在系统蓝牙处于 .poweredOn 状态时注册 GATT over BR/EDR 连接事件监听:
// 初始化 CBCentralManager
cbManager = CBCentralManager(delegate: self, queue: nil)
// 在 centralManagerDidUpdateState(_:) 中检查蓝牙状态
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
os_log("启动 cbManager")
let matchingOptions = [
CBConnectionEventMatchingOption.serviceUUIDs: [BTConstants.sampleServiceUUID]
]
cbManager.registerForConnectionEvents(options: matchingOptions)
case .poweredOff:
os_log("蓝牙当前处于关闭状态")
default:
break
}
}
示例 4:构建配置(xcconfig)
SAMPLE_CODE_DISAMBIGUATOR=${DEVELOPMENT_TEAM}
Source: SampleCode.xcconfig
故障排查与环境边界
环境不满足时的典型表现
| 现象 | 可能原因 | 处理建议 |
|---|---|---|
编译报错,找不到 registerForConnectionEvents | 部署目标低于 iOS 13.0,或 Xcode 版本过旧 | 将工程 Deployment Target 设为 iOS 13.0+,升级至 Xcode 14.0+ |
| 运行时日志只输出“蓝牙当前处于关闭状态”,无连接事件 | 系统蓝牙未开启(.poweredOff 分支) | 在设置中打开蓝牙后重新运行 |
| 启动后无权限弹窗,扫描/连接无响应 | Info.plist 缺少 NSBluetoothAlwaysUsageDescription | 补充权限描述键值后重新构建 |
| 模拟器上无法发现 BR/EDR 设备 | 模拟器不支持经典蓝牙(BR/EDR)硬件模拟 | 使用真机(iOS 13.0+)测试 GATT over BR/EDR |
| 构建签名失败(Bundle ID 冲突) | 未设置开发团队,SAMPLE_CODE_DISAMBIGUATOR 为空 | 在 Xcode Signing 中设置 Development Team |
| 用户拒绝蓝牙授权后功能失效 | 权限被拒后系统不会回调连接事件 | 引导用户在 设置 → 隐私 → 蓝牙 中重新开启 |
边界与并发注意点
- 权限是一次性决策:iOS 13+ 的蓝牙授权弹窗只在首次初始化
CBCentralManager时出现,拒绝后需手动到系统设置中开启,App 内无法再次弹窗。 - 连接事件维护的并发一致性:示例在
peerConnected时向cbPeripherals追加、peerDisconnected时移除外设,并在主线程调用tableView.reloadData();回调均由系统在主线程派发,因此列表操作无需额外加锁,但若自行扩展为多线程处理,需注意数组的线程安全。 @unknown default分支:示例对未知事件类型使用fatalError("Unhandled event type"),表明协议演进时新增事件会导致显式崩溃,提醒开发者及时适配新系统版本。
性能与运维建议
- 首次导入时 Xcode 会进行索引(Indexing),大工程建议等待索引完成后再 Run,避免首次编译缓慢。
- 示例无第三方依赖,
Clean Build Folder(⇧⌘K)后重新编译通常能解决大部分异常构建问题。 - 真机调试需在 Xcode 中注册设备的 Apple ID 并配置签名(Signing & Capabilities),这与
SAMPLE_CODE_DISAMBIGUATOR的自动派生机制配合即可生成唯一 Bundle ID。 - 若需在 CI 中自动化构建,可基于
xcodebuild -project CoreBluetoothClassicSample.xcodeproj -scheme CoreBluetoothClassicSample执行,并确保构建机安装 Xcode 14.0+ 与 iOS 13.0+ 的 SDK。
扩展点
- 权限文案定制:修改
Info.plist中NSBluetoothAlwaysUsageDescription为应用专属文案;新增UIBackgroundModes中的bluetooth-central以支持后台连接。 - 构建配置调整:
SampleCode.xcconfig可继续追加自定义构建变量(如调试/发布差异配置),Xcode 的 Build Settings 中可查看其最终展开值。 - 新增示例工程:仓库根目录的
ios-bt-demo/预留了“更多示例持续更新中”的目录规划,新示例按UsingCoreBluetoothClassic/的目录规范(xcodeproj + 源码 + README + LICENSE)放置即可被文档中心索引。
Related Links
- README.md(仓库总览与快速开始)
- UsingCoreBluetoothClassic/README.md(示例工程详细说明)
- SampleCode.xcconfig(构建配置)
- CentralViewController.swift(连接事件监听实现)
- Info.plist(应用权限配置)
- 示例运行时逻辑(服务发现、数据收发)详见
UsingCoreBluetoothClassic示例说明页