面试题答案
一键面试整体架构设计思路
- 中心管理器(Central Manager):
- 创建一个
CBCentralManager
实例来管理与蓝牙设备的交互。该实例负责扫描周边设备、连接设备以及监控蓝牙状态变化。 - 在
CBCentralManagerDelegate
协议方法中处理蓝牙状态变化,例如当蓝牙开启时开始扫描设备。
- 创建一个
- 设备连接管理:
- 为每个要连接的蓝牙设备创建一个独立的
CBPeripheral
实例。 - 使用一个数组或字典来存储所有的
CBPeripheral
实例,以便统一管理。例如,可以使用字典,以设备的identifier
作为键,CBPeripheral
实例作为值。 - 在扫描到设备后,通过调用
CBCentralManager
的connectPeripheral:options:
方法来连接设备,并在CBCentralManagerDelegate
的centralManager:didConnectPeripheral:
方法中处理连接成功的情况。
- 为每个要连接的蓝牙设备创建一个独立的
- 服务与特征发现:
- 连接成功后,在
centralManager:didConnectPeripheral:
方法中,调用CBPeripheral
的discoverServices:
方法来发现设备支持的服务。 - 在
CBPeripheralDelegate
的peripheral:didDiscoverServices:
方法中,遍历发现的服务,并对每个服务调用discoverCharacteristics:forService:
方法来发现服务中的特征。 - 在
peripheral:didDiscoverCharacteristicsForService:error:
方法中,处理发现的特征,根据特征的UUID确定要读取或订阅数据的特征。
- 连接成功后,在
- 数据接收与处理:
- 对于要接收数据的特征,调用
setNotifyValue:forCharacteristic:
方法订阅通知,以便设备有数据更新时能收到通知。 - 在
CBPeripheralDelegate
的peripheral:didUpdateValueForCharacteristic:error:
方法中处理接收到的数据。由于可能同时有多个设备的数据到达,需要根据CBPeripheral
实例或特征的UUID来区分不同设备的数据。 - 为每个设备或特征创建独立的队列(如
dispatch_queue_t
)来处理数据,避免不同设备数据处理过程中的冲突。例如,当接收到数据后,将数据处理任务提交到对应的设备队列中进行处理。
- 对于要接收数据的特征,调用
- 避免数据冲突:
- 队列隔离:如上述提到,为每个设备或特征相关的数据处理任务使用独立的队列,保证同一时间只有一个任务在处理特定设备的数据,避免多线程同时访问和修改数据。
- 加锁机制:如果在某些情况下需要共享资源(如全局数据结构),可以使用锁(如
NSLock
或dispatch_semaphore
)来确保在同一时间只有一个线程能访问共享资源。例如,当更新一个全局的设备数据统计信息时,先获取锁,更新完成后再释放锁。