CoreBluetooth:如何为许多特性设计代码(30 - 40)?

ors*_*aef 10 architecture software-design ios core-bluetooth cbperipheral

我搜索了一下,发现这可能是一个重复的问题:

多个CBPeripheral用于同一设备

我的问题是:

我有多个服务,它们共有大约30-40个特征(是的,我需要所有这些...).作为处理CoreBluetooth的起点,我总是使用Apple示例代码(CoreBluetooth温度传感器).

发现和服务/特征处理分为两类,这只适用于几个特征.但是在一个类中处理这么多的特性并不是我在"良好的软件设计"中所理解的.

进入脑海的第一个想法是为每个服务创建一个类.但不幸的是,CBPeripheral只能同时拥有一个CBPeripheralDelegate.这意味着我不能把它分成几个类.

(如果BLE是获取此类数据的正确技术,我们不必开始讨论 - 事实并非如此.但是有些制造商使用BLE,因此他们不必为MFi计划烦恼......)

我还阅读了最终提供的CoreBluetooth编程指南,但它只描述了基本的工作流程 - 没有关于正确的设计.

我正在寻找一个很好的设计方法.您可能有任何建议,提示或示例代码链接?提前谢谢了!

all*_*rog 9

将逻辑分解为几个自包含的类总是很好的设计.您一定要尝试根据服务或其他类别对代码进行分组.即使外围设备只有一个委托,您也可以轻松实现调度程序模式,您可以在其中注册各种服务实现和选择键(实际上是服务对象),并将调用分派给指定的服务处理程序.如果服务类实现了CPPeripheralDelegate协议,那么如果您需要对代码进行最小的更改,则此设计将允许您单独测试/重用每个服务.

在伪obj-c代码中,调度程序外围代理看起来如下所示:

// The ivar/property serving as the registry
NSMutableDictionary *registeredHandlers = [[NSMutableDictionary alloc] init];

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
  // for each service create an instance of its handler class and
  // add them to the registered handlers
  for (CBService *service : peripheral.services) {
    if (!registeredHandlers[service]) { // don't reinitialize if not needed
      ExtendedCBPeripheralDelegate *serviceHandler = [self instantiateHandlerForService:service];
      [registeredHandlers setObject:serviceHandler forKey:service];
      [serviceHandler discoverCharacteristics]; // make this functionality self contained for the service
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在服务或特征相关的回调中,应该实施调度.一个例子:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
  ExtendedCBPeripheralDelegate *serviceHandler = registeredHandlers[service];
  [serviceHandler peripheral:peripheral didDiscoverCharacteristicsForService:service error:error];
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
  ExtendedCBPeripheralDelegate *serviceHandler = registeredHandlers[characteristic.service];
  [serviceHandler peripheral:peripheral didWriteValueForCharacteristic:characteristic error:error];
}
Run Code Online (Sandbox Code Playgroud)

如果中央管理器关闭,那么最好的解决方案是放弃整个外围代理.不要为重新初始化而烦恼,而是计划处置.当然,如果需要,您可以通知服务处理程序即将发生的破坏.

  • 一方面注意:我记得当我使用NSNotifications这些数据时,这确实最终出现在一个冻结的应用程序中.通知风暴对于传输数据真的不是一个好主意......(很久以前我做过这个,但我认为这仍然是任何iOS新手的重要信息) (2认同)