我遇到信号量问题。 我有一系列的块,我希望在前一个块完成其工作时执行一个块。 我红了,我必须使用gcd信号量,但应用程序停止在代码中签名的点工作,它永远不会进入块completation。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSLog(@"1. AZIENDE: BEGIN");
[Model syncAziende:^(id response, NSError *error) {
dispatch_semaphore_signal(semaphore);
NSLog(@"2. AZIENDE: FINISH");
}];
/*BLOCKS HERE */dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"3. AZIENDE: BEGIN");
[Model syncContatti:^(id response, NSError *error) {
NSLog(@"4. AZIENDE: FINISH");
}];
这是输出:
2014-03-26 09:35:56.561 NSalesCDC [1071:60b] 1. AZIENDE:BEGIN
答案 0 :(得分:0)
尝试使用信号量不是正确的方法。 相反,将回调链接在一起。你可以在彼此之外创建你的块,以防止可怕的金字塔般的回调地狱。
这应该适合你:
// The block that is called when syncContatti: is complete
void (^contattiBlock)(id, NSError *) = ^(id response, NSError *error) {
NSLog(@"4. AZIENDE: FINISH");
};
// The block that is called when syncAziende: is complete
void (^aziendeBlock)(id, NSError *) = ^(id response, NSError *error) {
NSLog(@"2. AZIENDE: FINISH");
// Now, we know that syncAziende: is finished, we can start the next step
[Model syncContatti:conCattiBlock];
};
// Now we begin the entire chain of events
NSLog(@"1. AZIENDE: BEGIN");
[Model syncAziende:aziendeBlock];
这样做的一个缺点是你必须按相反顺序定义你的块,但这不是太糟糕。
答案 1 :(得分:0)
您可以使用dispatch_barrier_async()
。 dispatch_barrier_async()
将等待在屏障之前安排完成执行的所有任务,然后它将开始执行。屏障后安排的所有任务都将等待屏障完成。
dispatch_async(myQueue,
// this will start working now
});
dispatch_barrier_async(myQueue,
// this will wait until the previous block finish
//and will block the next one from execution
})
dispatch_async(myQueue,
// this will wait for the barrier to finish
});
答案 2 :(得分:0)
您可以使用NSOperation依赖项。 E.g。
NSOperationQueue * que = [[NSOperationQueue alloc] init];
NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"first");
}];
NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"second");
}];
[op2 addDependency:op];
[que addOperations:@[op,op2] waitUntilFinished:NO];
您也可以在第一个区域内调用第二个区块或使用其他方法
答案 3 :(得分:0)
如果您对上述评论的回复确实是您的代码结构,那么它会呼吁进行重构。重复是一个很好的抽象候选者。
也许是这样的:
static const struct {
SEL selector;
NSString* message;
} steps[] = {
{ @selector(syncAziende:), @"Sincrinizzo i contatti" }.
{ @selector(syncContatti:), @"Sincrinizzo le destinazioni" }.
// ...
};
- (void) doStep:(int) step
{
if (step < sizeof(steps) / sizeof(steps[0]))
{
[Model performSelector:steps[step].selector withObject:[^(id response, NSError *error){
hud.labelText = [NSString stringWithFormat:@"%d/%d: %@", step + 1, sizeof(steps) / sizeof(steps[0]), steps[step].message];
[self doStep:step + 1];
} copy]];
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
hud.mode = MBProgressHUDModeText;
hud.labelText = @"Sincronizzazione terminata";
[hud hide:YES afterDelay:1.5];
});
}
}
...
[self doStep:0];
答案 4 :(得分:0)
以这种方式使用:
- (void) testSomethingAPI
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[Model syncAziende: ^(id response, NSError *error)
{
// Your Stuff here...
dispatch_semaphore_signal(semaphore);
}];
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW))
{
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate dateWithTimeIntervalSinceNow: 1.f]];
}
}