我正在使用CoreBluetooth
与使用低功耗蓝牙的外围设备连接和交换数据。要连接到我的外设,我使用以下方法(为了清晰起见,manager
是CBCentralManager
类的一个实例)。获取使用GCD和信号量的异步方法
- (void)connectPeripheral:(CBPeripheral *)peripheral {
// Connects with the peripheral
[manager connectPeripheral:peripheral options:nil];
}
现在我想用Grand Central Dispatch,blocks和信号量来编写这个方法的异步版本。我希望有一个版本在特定的时间间隔内超时。首先,我所限定的本方法:
void dispatchAsyncWithCompletionAndTimeout(dispatch_queue_t queue, int64_t timeoutInNanoseconds,
dispatch_block_t block, dispatch_block_t completionBlock,
dispatch_block_t timeoutBlock) {
NSCParameterAssert(queue);
NSCParameterAssert(timeoutInNanoseconds >= 0);
NSCParameterAssert(block);
dispatch_async(queue, ^{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_time_t timeoutTime = dispatch_time(DISPATCH_TIME_NOW, timeoutInNanoseconds);
dispatch_async(queue, ^{
long timedOut = dispatch_semaphore_wait(semaphore, timeoutTime);
if (timedOut) {
if (timeoutBlock) {
timeoutBlock();
}
} else if (completionBlock) {
completionBlock();
}
});
block();
dispatch_semaphore_signal(semaphore);
});
}
该函数基本上包含3个部分:第一是动作块(例如连接),而第二和第三个是处理程序块,其应该被称为是否进行了动作代码在超时过期之内或之后。
我所做其次是通过包装它下面的方法里面把我的connectPeripheral:
方法为异步方法:
- (void)connectPeripheralAnsync:(CBPeripheral *)peripheral withinTimeout:(NSInteger)timeout {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatchAsyncWithCompletionAndTimeout(queue, (int64_t)timeout * NSEC_PER_SEC, ^{
[self connectPeripheral:peripheral];
}, ^{
NSLog(@"Peripheral discovered");
}, ^{
NSLog(@"Time runned out");
});
}
不幸的是我的第三块不会被调用,即使没有外围设备可以由被发现经理,直到超时过期。我在哪里失败?