【发布时间】:2015-10-30 13:51:40
【问题描述】:
我正在使用 cryptotokenkit 从智能卡发送/接收数据。用例是,在我做其他事情之前,我必须得到卡片 API 的响应。
在我的例子中,我发现这条线总是在 kMaxBlockingTimeSmartCardResponse (= 10) 秒后被调用。 来自
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
直接去
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kMaxBlockingTimeSmartCardResponse * NSEC_PER_SEC));
dispatch_semaphore_wait(sema, timeout);
然后等待 10 秒来进行块调用。它不是块回调延迟。如果我将调度时间设置为 20 或 30 秒,它会等待 20 或 30 秒执行。等待调用真正等待指定的时间然后执行回调块。
我做错了什么?我想知道这是否与 adObserver 有关。
- (void) updateSlots {
self.slotNames = [self.manager slotNames];
self.slotModels = [NSMutableArray new];
self.slots = [NSMutableArray new];
if([self.slotNames count] > 0)
{
for (NSString *slotName in self.slotNames)
{
NSLog(@"SmartCard reader found: %@", slotName);
// semaphore BLOCK starts
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self.manager getSlotWithName:slotName reply:^(TKSmartCardSlot *slot)
{
if (slot) {
SCSlotModel *slotModel = [SCSlotModel new];
[self.slotModels addObject:slotModel];
[self.slots addObject:slot];
[slot addObserver:self forKeyPath:@"state"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionInitial
context:nil];
slotModel.suffixedName = slotName; // NOT slot.name; original name is suffixed with 01, 02 etc.
slotModel.slot = slot;
slotModel.cardStatus = [CardUtil mapCardStatus:slot.state];
DLog(@"slot: %@, slotmodel: %@",slot.name, slotModel);
} else {
NSLog(@"Did not find slot with name: %@", slotName);
}
dispatch_semaphore_signal(sema);
}];
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kMaxBlockingTimeSmartCardResponse * NSEC_PER_SEC));
dispatch_semaphore_wait(sema, timeout);
// semaphore BLOCK ends
self.errorCode = SCPNoError;
}
} else {
NSLog(@"No slot available.");
self.errorCode = SCPErrorReaderNotFound;
}
}
getSlotWithName 是来自TKSmartCardSlotManager 的方法
/// Instantiates smartcard reader slot of specified name. If specified name is not registered, returns nil.
- (void)getSlotWithName:(NSString *)name reply:(void(^)(TKSmartCardSlot *__nullable slot))reply;
但在其他地方,对于相同类型的异步调用,它按预期工作。
- (BOOL) beginSession:(TKSmartCard *)card
{
__block BOOL response = NO;
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[card beginSessionWithReply:^(BOOL success, NSError *error) {
response = success;
if (!success) {
NSLog(@"Could not begin session.");
}
if (error) {
NSLog(@"Could not begin session with error %@", error);
}
dispatch_semaphore_signal(sema);
}];
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kMaxBlockingTimeSmartCardResponse * NSEC_PER_SEC));
dispatch_semaphore_wait(sema, timeout);
return response;
}
【问题讨论】:
-
您将从应用异步编程风格中受益。由于您的
updateSlots方法使用异步方法,因此该方法也变为异步:将完成块的参数添加到updateSlots并在getSlotWithName的完成处理程序reply中调用此块。然后使用延续调用updateSlots,即完成块-并执行您想做的任何事情以继续。 -
谢谢。我会试试的。但在其他地方它按预期工作。用那部分更新了我的代码。
标签: xcode macos callback objective-c-blocks semaphore