最近公司的项目涉及到了蓝牙开发,在开发的过程中遇到了一个问题,怎么将蓝牙代理方法中异步返回的数据同步出来.
查了一下资料,知道dispatch_semaphore_t(信号量)可以解决这个问题,好了废话不多说,直接上代码:
首先定义一个block来返回蓝牙是否连接成功
typedefvoid(^ConnectBlock)(BOOLisCon);
@property (copy, nonatomic) ConnectBlock connectBlock;//声明属性
-(BOOL)ConnectTheBluetooth {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block BOOL iscon;
self.connectBlock= ^(BOOLisCon) {
iscon = isCon;
dispatch_semaphore_signal(sema);
};
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return iscon;
}
//蓝牙代理方法
//连接到Peripherals-成功
- (void)centralManager:(CBCentralManager*)central didConnectPeripheral:(CBPeripheral*)peripheral {
// Detect the Bluetooth reader.
if (self.connectBlock) {
self.connectBlock(YES);
}
}
//连接到Peripherals-失败
- (void)centralManager:(CBCentralManager*)central didFailToConnectPeripheral:(CBPeripheral*)peripheral error:(NSError*)error {
// Show the error
if(error !=nil) {
if(self.connectBlock) {
self.connectBlock(NO);
}
}
}
但是,在代码运行的时候发现根本就不走block里面的方法,线程直接卡住了,这就很难受了,没办法只有继续摸索了,后来查了一下资料才发现问题出在了蓝牙初始化方法:
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
初始化蓝牙的时候queue填的nil,默认是主线程
外部在调用- (BOOL)ConnectTheBluetooth方法的时候,创建的总信号量为0,代码执行到代码执行到dispatch_semaphore_wait时, 主线程阻塞,直到收到信号才会往下继续执行;
dispatch_semaphore_signal(s)发送信号是放在主线程中执行,由于此时主线程是阻塞的,那么dispatch_semaphore_signal(s)不会执行,这形成了死锁的情况。
所以正确的做法是开辟一个线程来初始化蓝牙,
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:queue];
这样蓝牙的代理方法在子线程中进行,外部调用- (BOOL)ConnectTheBluetooth方法的时候,主线程卡在dispatch_semaphore_wait时,子线程还在走,走到蓝牙的代理方法中,执行block回调方法:
self.connectBlock= ^(BOOLisCon) {
dispatch_semaphore_signal(sema);
};
dispatch_semaphore_signal(s)发送信号,使主线程继续执行,这样就可以实现同步代理返回的数据了.