最近公司的項(xiàng)目涉及到了藍(lán)牙開發(fā),在開發(fā)的過程中遇到了一個(gè)問題,怎么將藍(lán)牙代理方法中異步返回的數(shù)據(jù)同步出來.
查了一下資料,知道dispatch_semaphore_t(信號(hào)量)可以解決這個(gè)問題,好了廢話不多說,直接上代碼:
首先定義一個(gè)block來返回藍(lán)牙是否連接成功
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;
}
//藍(lán)牙代理方法
//連接到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);
? ? }
? ? }
}
但是,在代碼運(yùn)行的時(shí)候發(fā)現(xiàn)根本就不走block里面的方法,線程直接卡住了,這就很難受了,沒辦法只有繼續(xù)摸索了,后來查了一下資料才發(fā)現(xiàn)問題出在了藍(lán)牙初始化方法:
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
初始化藍(lán)牙的時(shí)候queue填的nil,默認(rèn)是主線程
外部在調(diào)用- (BOOL)ConnectTheBluetooth方法的時(shí)候,創(chuàng)建的總信號(hào)量為0,代碼執(zhí)行到代碼執(zhí)行到dispatch_semaphore_wait時(shí), 主線程阻塞抖坪,直到收到信號(hào)才會(huì)往下繼續(xù)執(zhí)行;
dispatch_semaphore_signal(s)發(fā)送信號(hào)是放在主線程中執(zhí)行季二,由于此時(shí)主線程是阻塞的浦马,那么dispatch_semaphore_signal(s)不會(huì)執(zhí)行颁湖,這形成了死鎖的情況。
所以正確的做法是開辟一個(gè)線程來初始化藍(lán)牙,
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
? ? _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:queue];
這樣藍(lán)牙的代理方法在子線程中進(jìn)行,外部調(diào)用- (BOOL)ConnectTheBluetooth方法的時(shí)候,主線程卡在dispatch_semaphore_wait時(shí),子線程還在走,走到藍(lán)牙的代理方法中,執(zhí)行block回調(diào)方法:
?self.connectBlock= ^(BOOLisCon) {
? ? ? ?dispatch_semaphore_signal(sema);
? ? };
dispatch_semaphore_signal(s)發(fā)送信號(hào),使主線程繼續(xù)執(zhí)行,這樣就可以實(shí)現(xiàn)同步代理返回的數(shù)據(jù)了.