我一直在尝试在返回结果的方法中使用dispatch_async
。但是,我观察到该方法在执行dispatch_async
块之前返回。由于这个原因,我没有得到我期望的结果。这是一些演示我问题的代码。
-(BOOL) isContactExists {
BOOL isContactExistsInXYZ = YES;
UserId *userId = contact.userId;
dispatch_async(dispatch_get_main_queue(), ^
{
iOSContact *contact = [iOSContact contactForUserId:userId];
if (nil == contact)
{
isContactExistsInXYZ = NO;
}
});
return isContactExistsInXYZ;
}
此方法isContactExists
在其他地方被调用,并且基于该方法的响应,我必须做一些事情。但每一次,isContactExistsInXYZ
的价值都不是我所期望的。有人可以解释在这种情况下如何处理dispatch_async
吗?
感谢。
答案 0 :(得分:10)
如果您进入阻止路线,您的方法需要看起来像这样。
- (void)isContactExistsWithCompletionHandler:(void(^)(BOOL exists)) completion
{
dispatch_async(dispatch_get_main_queue(), ^
{
BOOL isContactExistsInXYZ = YES;
UserId *userId = contact.userId;
iOSContact *contact = [iOSContact contactForUserId:userId];
if (nil == contact)
{
isContactExistsInXYZ = NO;
}
completion(isContactExistsInXYZ);
});
}
你在哪里称之为。
[someObject isContactExistsWithCompletionHandler:^(BOOL exists) {
// do something with your BOOL
}];
您还应该考虑将重型操作放在除主要操作之外的其他操作中。像这样。
- (void)isContactExistsWithCompletionHandler:(void(^)(BOOL exists)) completion
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL);
dispatch_async(queue, ^
{
BOOL isContactExistsInXYZ = YES;
UserId *userId = contact.userId;
iOSContact *contact = [iOSContact contactForUserId:userId];
if (nil == contact)
{
isContactExistsInXYZ = NO;
}
dispatch_async(dispatch_get_main_queue(), ^
{
completion(isContactExistsInXYZ);
});
});
}
答案 1 :(得分:6)
你需要尊重你想要做的事情是异步的并拥抱它。这意味着不使用返回值。相反,您可以编写您的方法以将回调块作为参数。然后,当您的异步检查完成后,您可以使用结果调用该块。
所以你的方法签名会变成:
- (void)checkIfContactExistsWithCompletion:(ContactExistsBlock)completion {
其中ContactExistsBlock
是一个没有返回的块定义,可能还有一个BOOL
参数。
typedef void (^ContactExistsBlock) (BOOL exists);
答案 2 :(得分:3)
原因是dispatch_async(dispatch_get_main_queue(), ^
不等到执行完成。你可能搞乱那里的东西。通常,这用于异步更新UI以及在其他某个线程中下载的其他服务器内容。请尝试使用dispatch_sync
。