7

我一直在尝试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

4

3 回答 3

15

如果你走块路线,你的方法需要看起来像这样。

- (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
}];

您还应该考虑将繁重的操作放在除 main 之外的其他队列中。像这样。

- (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);
        });
    });
}
于 2013-10-22T20:21:17.180 回答
6

您需要尊重您正在尝试做的事情是异步的并接受它。这意味着不使用返回值。相反,您可以编写方法以将回调块作为参数。然后,当您的异步检查完成时,您可以使用结果调用该块。


所以你的方法签名会变成:

- (void)checkIfContactExistsWithCompletion:(ContactExistsBlock)completion {

WhereContactExistsBlock是一个没有返回且可能只有一个BOOL参数的块定义。

typedef void (^ContactExistsBlock) (BOOL exists);
于 2013-10-22T18:20:19.727 回答
3

原因是dispatch_async(dispatch_get_main_queue(), ^不等到执行完成。你可能在那里搞砸了。通常,这用于异步更新 UI 以及在其他线程中下载的其他服务器内容。尝试 dispatch_sync改用。

于 2013-10-22T18:25:17.060 回答