WWDC Quick Look 💓 By SwiftGGTeam
Get timely alerts from Bluetooth devices on watchOS

Get timely alerts from Bluetooth devices on watchOS

观看原视频

Highlight

Apple Watch 通过 Core Bluetooth 与外部配件通信,让蓝牙设备能够在后台发现、持续监控特征变化,并通过 complications 定期展示数据,最终向用户发送及时的本地通知。


核心内容

Apple Watch 和 iPhone 不同。它戴在手腕上,需要省电,后台限制更严。

但用户希望手腕上的设备能实时收到蓝牙配件的提醒——血糖异常、心率超标、门锁被打开。这些提醒不能等用户打开 App 才送达,它们必须主动推过来。

这场 Session 讲了三个关键技术:complications 的周期性数据更新、后台外设发现、以及特征变化监听。三者组合在一起,构成了 watchOS 上蓝牙配件实时提醒的完整链路。

详细内容

通过特征通知监听蓝牙数据

03:41)蓝牙配件通过 GATT 协议组织数据。服务(Service)是功能分组,特征(Characteristic)是实际的数据点。当配件有新数据时,它可以通过特征通知主动推送给 Apple Watch。

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    peripheral.setNotifyValue(true, for: characteristic)
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    if let newData = characteristic.value {
        // Post a local notification.
    }
}

关键点:

  • didDiscoverCharacteristicsFor 在发现服务下的特征后触发。
  • setNotifyValue(true, for:) 开启该特征的通知,让配件在有新数据时推送。
  • didUpdateValueFor 在特征值更新时被调用。
  • characteristic.value 拿到的是 Data 类型,需要按配件协议解析。
  • 拿到有效数据后,可以触发本地通知让用户看到提醒。

核心思路很直接:订阅特征通知,收到数据后发本地通知。用户不需要打开 App,提醒会自动出现在手腕上。

后台外设发现

09:15)watchOS 上的蓝牙扫描不能像 iOS 那样随意。前台扫描会影响电池,后台扫描受限更多。Session 给出了一种策略:连接成功后再次发起扫描,让系统在合适的时机发现其他配件。

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
    central.scanForPeripherals(withServices: [myCustomUUID])
}

关键点:

  • didConnect 在成功连接到某个外设后触发。
  • 连接成功后立即发起新的扫描,按指定服务 UUID 过滤。
  • 传入 myCustomUUID 只扫描带有特定服务的外设,减少不必要的功耗。
  • 这种”连接一个再扫下一个”的策略适合 watchOS 的后台限制。

Apple Watch 上不能一直开着扫描。更好的做法是:知道要连什么服务,在合适的时机(比如连接成功后)再发起有限的扫描。系统会管理扫描窗口,平衡发现需求和电池续航。

Complications 的周期性数据展示

Session 虽然没有提供具体代码,但讲到了 complications 作为周期性数据入口的角色。

蓝牙配件的数据变化可能不频繁——比如每 5 分钟测一次血糖,或每小时更新一次环境温度。complications 适合这种场景:系统按时间线(timeline)请求数据,表盘上显示最新的读数。配件通过 Core Bluetooth 更新数据时,App 刷新 complications 的时间线,用户在抬腕瞬间就能看到最新值。

关键点:

  • complications 的数据通过时间线条目(timeline entries)驱动。
  • 每次蓝牙数据更新后,调用 CLKComplicationServerreloadTimeline 刷新表盘。
  • 时间线不能太密——系统对刷新频率有限制,建议合理设置条目间隔。
  • 结合特征通知:收到新数据 -> 更新本地缓存 -> 刷新 complications 时间线 -> 发本地通知。

这三步形成了一个闭环:配件推送数据 -> complications 展示最新值 -> 关键事件触发通知。用户不需要主动操作,数据自己流动到手腕上。


核心启发

1. 用特征通知替代轮询

  • 做什么:让蓝牙配件通过 GATT 通知主动推送数据,而不是让 Apple Watch 定时查询。
  • 为什么值得做:轮询会频繁唤醒蓝牙模块,耗电明显。通知机制让配件在数据就绪时才发,更省电也更实时。
  • 怎么开始:在配件端实现 GATT 通知,App 端调用 setNotifyValue(true, for:) 订阅。收到数据后先判断是否值得提醒(阈值判断),再决定是否发通知。

2. 把后台扫描设计成”按需发现”

  • 做什么:不要一直扫描外设。在连接一个配件后、或用户明确请求时再发起有限扫描。
  • 为什么值得做:watchOS 对后台扫描比 iOS 严格得多,持续扫描会快速消耗电量并可能被系统终止。
  • 怎么开始:在 didConnect 回调中调用 scanForPeripherals(withServices:),传入已知的服务 UUID。连接成功后可以停止扫描。

3. 让 complications 成为数据中转站

  • 做什么:把蓝牙配件的定期数据通过 complications 展示在表盘上。
  • 为什么值得做:用户在抬腕时就能看到最新读数,不需要打开 App。complications 的刷新节奏天然适合低频传感器数据。
  • 怎么开始:在 Core Bluetooth 的数据回调中更新本地缓存,然后调用 reloadTimeline 刷新 complications。合理设置时间线条目的间隔,不要超出系统限制。

4. 阅读配件设计指南

  • 做什么:在设计蓝牙配件前,先阅读 Apple 的 Accessory Design Guidelines。
  • 为什么值得做:这份文档规定了配件的蓝牙行为、功耗要求和交互模式,提前对齐可以避免审核被拒或用户体验差。
  • 怎么开始:从 Accessory Design Guidelines 开始,重点关注 watchOS 相关的章节。

关联 Session

评论

GitHub Issues · utterances