【发布时间】:2015-03-06 09:48:15
【问题描述】:
我正在开发一个应用程序,它将通过 CoreBluetooth (BLE) 接收数据并将其与 CoreData 一起存储。它们单独工作得很好,但不能一起工作,我认为这与线程有关。
我做什么
我使用单例来处理 CoreData 交互。单例初始化代码如下。初始化代码基本上是斯坦福课程 CS193p 的复制粘贴。
第一次访问单例是当 CoreBluetooth 从蓝牙外围设备接收到某个数据块时。请参阅下面的代码。
单例初始化
static SessionManager *sharedInstance;
+ (instancetype)sharedSessionManager
{
NSLog(@"Shared instance requested.");
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
第一次 SessionManager 访问
-(void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
// First some data processing
...
[[SessionManager sharedSessionManager] addMessageToCurrentSession:message];
}
会发生什么
在-(instancetype) init 内部,整个应用程序在下面的行冻结(零 CPU,没有内存增加)。
当断点到达这一点时(即在它执行之前),我还添加了线程的图像。
[self.document openWithCompletionHandler:^(BOOL success) {
if (success) [self documentIsReady];
if (!success) NSLog(@"Could not open document %@", [self.documentPath path]);
}];
我的问题
发生了什么,我做错了什么?
【问题讨论】:
-
在
init中调用异步方法是个坏主意。无论如何,Singleton 是个坏主意。您应该用普通类替换会话管理器单例并使用依赖注入。然后您可以从init中删除异步方法 -
感谢您的评论!我不能只是从
init移动异步吗?例如,我第一次需要访问不在init的文档。我也从这里获得了灵感,他/她似乎也遵循了类似的方法。 themainthread.com/blog/2012/03/… -
是的,你可以使用这种方法,但你应该尝试让自己摆脱单身
-
嗯,试过了,没用。 :/ 题外话:我知道有很多关于这个的讨论,但是你的不使用单例的论点是什么?在这种情况下,我需要从多个位置与之交互的单个实体(数据库),但我知道要小心使用它们。
-
您看到的问题是针对 Singletons 的经典案例 - 使用 DI,您可以轻松注入 null 或模拟
SessionManager,以便将 BT 与数据库函数分开测试
标签: ios multithreading core-data core-bluetooth