我应该如何构建我的应用来处理传入的蓝牙数据?

时间:2015-05-06 18:46:43

标签: ios objective-c bluetooth bluetooth-lowenergy core-bluetooth

我正在开发一个项目,我有一个应用程序,通过可穿戴外围设备从BLE接收数据,但我在如何构建应用程序方面苦苦挣扎。目前我有一个单独的BLEManager类,它不断在后台接收数据,然后使用NSNotificationCenter将其发送到活动视图控制器。这有效,但已经变得混乱,似乎不理想,因为我有多个视图控制器,每个视图控制器以相同的方式处理数据,然后只是以不同的方式显示它。此外,有一些与数据处理相关的设置可以在app中更改,并且需要在任何地方都相同。如果BLEManager将数据发送到中央处理类然后处理后的数据被发送到活动视图控制器,那将是很好的,但我不确定设置它的最佳方法。

我可以将所有处理合并到BLEManager类中,但是它会变得非常臃肿和不直观,并且不会很好地继续前进。如果我创建一个单独的处理类,它是BLEManager的一个属性,那么如果我想从其他任何令人讨厌的地方获取或更改处理类中的任何变量,我必须通过BLEManager。我可以创建一个单例处理类,从BLEManager接收数据,然后将其发送到活动的VC,但我已经看到人们说避免单身,所以我不愿意使用另一个,即使这似乎是可能是一个很好的解决方案。

是否有标准或推荐的方法来构建iOS应用程序来处理来自蓝牙的传入数据,然后将其发送到需要的地方?

2 个答案:

答案 0 :(得分:1)

如果您创建了一个与BLE(其他人)进行通信的大型系统,BLEManager根本不应该是单身人士。这需要是一个能够处理所有蓝牙通信的对象(我相信它已经做到了)并通过委托报告相关数据。

此时您需要的是此对象的界面,在您的情况下最好是单身。此类应具有最小化的界面,以满足管理这些数据所需的内容,并且不应公开BLEManager。这意味着创建所有方法,例如从使用角度来看有意义的BLEManager的初始化。在某些情况下,这将复制您在BLEManager中已经完成的界面部分,并且某些方法很可能只是将消息转发给经理。

这个界面类在开始时似乎有点无用,但最终会挽救你的生命。您应该在此类中添加的是所有其他可能的附件,例如本地数据库管理器,API管理器,分析,模拟......

因此,对于您的具体情况,您的任务列表似乎是:

  • 创建一个能够通过蓝牙进行通信的BLEManager类。
  • 创建一个数据管理器类,该类能够处理,处理和存储来自所需输入的数据,例如BLEManager
  • 创建一个接口单例,其中包含核心所需的所有附件,例如BLEManager和数据管理器。单例应提供从使用角度来看有意义的公共接口,并包括委派系统或通知系统。

界面应如下所示:

标题

@protocol CoreManagerDelegate
- (void)coreManager:(CoreManager *)sender updatedData:(id)data;
@optional
- (void)coreManager:(CoreManager *)sender encounteredIssue:(NSError *)issue;

- (void)coreManager:(CoreManager *)sender changedConnectionState:(BluetoothConnectionState)isConnected; // BluetoothConnectionStateUnkown, BluetoothConnectionStateDisabled, BluetoothConnectionStateNotPaired, BluetoothConnectionStateConnected...
@end

@interface CoreManager : Singleton
@property (weak) id<CoreManagerDelegate> delegate;
- (void)initialize;

- (void)fetchBluetoothData;
- (id)getCurrentData;

@end

来源

@interface CoreManager()
@property BLEManager *bluetoothManager;
@property DataManager *dataManager;
@end

@implementation CoreManager
#pragma mark - Bluetooth manager attachment
- (void)fetchBluetoothData {
    [self.bluetoothManager fetchSomeData];
}
#pragma mark Delegate
- (void)BLEManager:(BLEManager *)sender receivedNewData:(id)data {
    // do data validation, log if needed, report...
    [self.dataManager insertNewData:data];
}
- (void)BLEManager:(BLEManager *)sender encounteredIssue:(NSError *)issue {
    // modify and evaluate the error if needed
    if([self.delegate respondsToSelector:@selector(coreManager:encounteredIssue:)]) {
        [self.delegate coreManager:self encounteredIssue:issue];
    }
    else {
        // log error ?
    }
    // send the error to a remote service
}
#pragma mark - Data manager attachment
- (id)getCurrentData {
    return [self.dataManager currentData];
}
#pragma mark Delegate
- (void)dataManager:(DataManager *)sender updatedData:(id)processedData {
    [self.delegate coreManager:self updatedData:processedData];
}
- (void)dataManager:(BLEManager *)sender encounteredIssue:(NSError *)issue {
    // modify and evaluate the error if needed
    if([self.delegate respondsToSelector:@selector(coreManager:encounteredIssue:)]) {
        [self.delegate coreManager:self encounteredIssue:issue];
    }
    else {
        // log error ?
    }
    // send the error to a remote service
}
@end

现在,这将保持一个非常干净和敏捷的代码。它将防止任何不必要的类或文件膨胀。它为测试和模拟数据提供了一个非常好的机会。从使用角度来看,添加其他功能将是透明的:例如,实现核心数据不会在项目的用户界面部分产生任何变化。

如果可能,id类型应由具体的自定义对象替换。即使错误和日志最好是自定义的,因此您可以在应用程序中轻松跟踪它们,随意启用和禁用它们。

注意:如果您认为将蓝牙管理器转换为普通对象而不是单例而进行的更改太大,您可能仍然将其保持为单例,并简单地覆盖getter以使其返回共享实例。

我确信还有许多其他好的做法,但这是我大多使用的,并且到目前为止已被证明是最好的。我希望它会对你有所帮助。

答案 1 :(得分:0)

我不知道标准的设计模式,但我已经看到Singleton BLEManager广泛使用。我的理解是你只想要一个处理BLE通道的对象。

为了防止BLEManager变得过于膨胀,您可以使用委派模式,并为每个需要处理的BLE消息使用不同的协议。这样,您的BLEManager就可以通过处理每种类型消息的委托来路由消息。

这样可以让您更好地分离顾虑,这样您的BLEManager就不会臃肿。然后,BLEManager将成为一个愚蠢的传递,消息处理程序代表中发生的实际工作。