我正在尝试进行共享操作,我在其中使用异步块调用函数,但在我的下一个if语句中,我需要获取在块中完成的值以继续。这是我的代码,它将突出更多细节。我听说过NSLock并尝试使用它,但它没有用,可能是我做了锁定,我对锁不太熟悉。
-(void) shareOperation
{
__block NSString *resultText;
BOOL continueSharing;
NSLock *conditionLock=[[NSLock alloc] init];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[conditionLock lock];
[self performSomeAsynchronousOperation completionBlock:^(NSError *tError, bool status)
{
dispatch_async(dispatch_get_main_queue(),
^{
if (status)
{
resultText = @"Operation completed. Would you like to continue?";
}
else
{
resultText = @" Operation failed. Would you still like to continue?";
}
UIAlertView *result = [UIAlertView alertViewWithTitle:nil message:resultText cancelButtonTitle:@"Cancel" otherButtonTitles:[NSArray arrayWithObjects:@"OK",nil] onDismiss:^(int buttonIndex)
{
NSLog(@"selected button index: %d",buttonIndex);
if (buttonIndex == 0)
{
continueSharing=YES;
[conditionLock unlock];
NSLog(@"We are continuing sharing :)");
}
}onCancel:^{
continueSharing=NO;
[conditionLock unlock];
NSLog(@"cancelled");
}]; [result show];
});
}];
});
}
//should continue only after earlier if block finishes, ie after getting the continueSharing value
if (continueSharing)
{
[self performSomeAnotherAsynchronousOperation];
}
}
答案 0 :(得分:5)
您可以使用信号量(其设计使得一个线程可以等待来自另一个线程的信号,而不是使用锁定(仅用于确保不会同时访问某些共享资源))这里)。
所以,你应该创建一个信号量:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
警报视图完成块将发出信号量信号:
dispatch_semaphore_signal(semaphore);
您想等待该信号的地方(performSomeAnotherAsynchronousOperation
之前):
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
我稍稍调整了你的代码,但最值得注意的是,通过确保dispatch_semaphore_wait
在后台队列中完成,它不会阻止主队列(你永远不想做)。另请注意,dispatch_semaphore_signal
不在if
语句中。这导致:
- (void)shareOperation
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__block BOOL continueSharing = NO;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self performSomeAsynchronousOperationWithCompletionBlock:^(NSError *tError, bool status){
dispatch_async(dispatch_get_main_queue(),^{
NSString *resultText;
if (status)
resultText = @"Operation completed. Would you like to continue?";
else
resultText = @"Operation failed. Would you still like to continue?";
UIAlertView *alertView = [UIAlertView alertViewWithTitle:nil message:resultText cancelButtonTitle:@"Cancel" otherButtonTitles:@[@"OK"] onDismiss:^(int buttonIndex) {
NSLog(@"selected button index: %d",buttonIndex);
if (buttonIndex == 0) {
continueSharing = YES;
NSLog(@"We are continuing sharing :)");
}
dispatch_semaphore_signal(semaphore);
} onCancel:^{
dispatch_semaphore_signal(semaphore);
NSLog(@"cancelled");
}];
[alertView show];
});
}];
// should continue only after earlier if block finishes, ie after getting the continueSharing value
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
if (continueSharing)
[self performSomeAnotherAsynchronousOperation];
});
}
更好的是,你不应该使用任何阻塞机制,如信号量(当然不在主队列上),而应该只是让警报视图的完成块直接启动进程的下一步骤本身。我知道你说这在你的场景中不实用,但它通常是处理这些场景的正确方法。
答案 1 :(得分:0)
您可以使用延迟块
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC);
dispatch_after(delayTime, dispatch_get_main_queue(), ^(void){
})