BLE + CoreData 导致冻结 (semaphore_wait_trap)

BLE + CoreData causes freeze (semaphore_wait_trap)

我正在开发一个应用程序,它将通过 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]);
}];

我的问题

这是怎么回事,我做错了什么?

您的问题是您的 SessionManager 单例初始化存在竞争条件 - 您的 SessionManager init 调用 openWithCompletionHandler 异步完成,因此 init returns 在对象实际 初始化之前。

我建议您从 SessionManager 实现一个委托,以便它可以在初始化完成时回调。