面试题答案
一键面试- 初始化Core Bluetooth框架
- 导入
<CoreBluetooth/CoreBluetooth.h>
头文件。 - 创建一个
CBCentralManager
实例来管理与蓝牙设备的连接,例如:
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
- 导入
- 扫描并连接设备
- 在
CBCentralManagerDelegate
的centralManagerDidUpdateState:
方法中检查蓝牙状态,确保蓝牙可用后开始扫描:
- (void)centralManagerDidUpdateState:(CBCentralManager *)central { if (central.state == CBCentralManagerStatePoweredOn) { [self.centralManager scanForPeripheralsWithServices:nil options:nil]; } }
- 实现
centralManager:didDiscoverPeripheral:advertisementData:RSSI:
方法来发现设备,并连接感兴趣的设备:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI { // 存储设备引用 self.discoveredPeripheral = peripheral; self.discoveredPeripheral.delegate = self; [self.centralManager connectPeripheral:self.discoveredPeripheral options:nil]; }
- 在
- 发现服务和特征
- 实现
centralManager:didConnectPeripheral:
方法,在连接成功后发现设备的服务:
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { [peripheral discoverServices:nil]; }
- 实现
peripheral:didDiscoverServices:
方法来发现服务中的特征,假设已知特征的UUID,可以直接获取:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { for (CBService *service in peripheral.services) { [peripheral discoverCharacteristics:@[YOUR_CHARACTERISTIC_UUID] forService:service]; } }
- 实现
- 接收数据
- 实现
peripheral:didDiscoverCharacteristicsForService:error:
方法,为特征设置通知:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { for (CBCharacteristic *characteristic in service.characteristics) { if ([characteristic.UUID isEqual:YOUR_CHARACTERISTIC_UUID]) { [peripheral setNotifyValue:YES forCharacteristic:characteristic]; } } }
- 实现
peripheral:didUpdateValueForCharacteristic:error:
方法来接收数据:
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { if (error) { // 错误处理 NSLog(@"Error receiving data: %@", error); return; } NSData *data = characteristic.value; // 数据解析 [self parseData:data]; }
- 实现
- 数据解析
- 假设数据有特定格式,例如是一系列的整数,可以这样解析:
- (void)parseData:(NSData *)data { NSUInteger length = data.length; const uint8_t *bytes = data.bytes; NSMutableArray *parsedData = [NSMutableArray array]; for (NSUInteger i = 0; i < length; i += sizeof(int)) { int value; memcpy(&value, &bytes[i], sizeof(int)); [parsedData addObject:@(value)]; } // 处理解析后的数据 NSLog(@"Parsed data: %@", parsedData); }
- 数据完整性
- 可以在数据格式中加入校验和字段。在发送端计算数据的校验和并附加在数据末尾,接收端在解析数据后重新计算校验和并与接收到的校验和对比。
- 例如,假设数据是一系列整数,可以这样计算校验和:
- (NSUInteger)calculateChecksum:(NSData *)data { NSUInteger sum = 0; const uint8_t *bytes = data.bytes; NSUInteger length = data.length; for (NSUInteger i = 0; i < length; i += sizeof(int)) { int value; memcpy(&value, &bytes[i], sizeof(int)); sum += value; } return sum; }
- 在解析数据时进行校验:
- (void)parseData:(NSData *)data { NSUInteger length = data.length; if (length < sizeof(NSUInteger)) { // 数据太短,不完整 NSLog(@"Data is incomplete"); return; } NSData *checksumData = [data subdataWithRange:NSMakeRange(length - sizeof(NSUInteger), sizeof(NSUInteger))]; NSUInteger receivedChecksum; [checksumData getBytes:&receivedChecksum length:sizeof(NSUInteger)]; NSData *contentData = [data subdataWithRange:NSMakeRange(0, length - sizeof(NSUInteger))]; NSUInteger calculatedChecksum = [self calculateChecksum:contentData]; if (calculatedChecksum != receivedChecksum) { // 校验和不匹配,数据可能损坏 NSLog(@"Checksum mismatch, data may be corrupted"); return; } // 继续正常解析数据 const uint8_t *bytes = contentData.bytes; NSMutableArray *parsedData = [NSMutableArray array]; for (NSUInteger i = 0; i < contentData.length; i += sizeof(int)) { int value; memcpy(&value, &bytes[i], sizeof(int)); [parsedData addObject:@(value)]; } NSLog(@"Parsed data: %@", parsedData); }
- 错误处理
- 在连接、发现服务/特征、接收数据等各个步骤的代理方法中处理错误,例如:
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"Failed to connect to peripheral: %@", error); } - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { if (error) { NSLog(@"Failed to discover services: %@", error); } } - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { if (error) { NSLog(@"Failed to discover characteristics: %@", error); } } - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { if (error) { NSLog(@"Error receiving data: %@", error); } }
- 内存优化
- 及时释放不再使用的对象,例如在断开连接后释放
CBPeripheral
等对象的引用:
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { self.discoveredPeripheral = nil; }
- 在数据处理过程中,避免不必要的中间数据副本。例如,在解析数据时尽量直接从
NSData
的字节数组中读取数据,而不是先转换为其他大对象。
- 及时释放不再使用的对象,例如在断开连接后释放
通过以上步骤,可以在Objective - C中利用Core Bluetooth框架高效接收、解析蓝牙传感器数据,并处理好数据完整性、错误以及内存使用问题。