dispatch_async in return method Objective-C

11,714

Solution 1

If your going the block route your method needs to look something like this.

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

And where you are calling it something like this.

[someObject isContactExistsWithCompletionHandler:^(BOOL exists) {
    // do something with your BOOL
}];

You should also consider placing your heavy operations in a other que than main. Like this.

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

Solution 2

You need to respect that what you are trying to do is asynchronous and embrace that. This means not using a return value. Instead you can write your method to take a callback block as a parameter. Then, when your asynchronous check is complete you can call the block with the result.


So your method signature would become:

- (void)checkIfContactExistsWithCompletion:(ContactExistsBlock)completion {

Where ContactExistsBlock is a block definition with no return and probably a single BOOL parameter.

typedef void (^ContactExistsBlock) (BOOL exists);

Solution 3

The reason is dispatch_async(dispatch_get_main_queue(), ^does not wait until execution is done. You are probably messing up stuff there. Normally, this is used to update UI asynchronously along with other server content getting downloaded in some other thread. Try using dispatch_sync instead.

Share:
11,714
Santosh Gurram
Author by

Santosh Gurram

Updated on June 08, 2022

Comments

  • Santosh Gurram
    Santosh Gurram about 2 years

    I have been trying to use dispatch_async in a method that returns a result. However, I observed that the method returns before executing the dispatch_async block. Due to this I'm not getting the results I expect. Here is some code that demonstrates my problem.

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

    This method isContactExists is called somewhere else and based on the response from that method I have to do some stuff. But every time, the value of isContactExistsInXYZ is not what I expect. How do I handle dispatch_async in this situation?

  • Santosh Gurram
    Santosh Gurram over 10 years
    Can u elaborate with a sample code or are you saying me to use "completion handler" block
  • Santosh Gurram
    Santosh Gurram over 10 years
    Here one thing I have to mention is that my requirement is that I have to run the operation in background thread, so I chosen to use dispatch_async over dispatch_sync. Can you please get me a logical information or to handle the same in other way. Thanks.
  • Abhinav
    Abhinav over 10 years
    You need to look into delegation pattern. There are plenty of examples in iOS framework. See how NSConnection works. It gives you a call back as soon as some data chunk is ready. So, probably, you need to perform your operation asynchronously and then handle the call back through delegate methods.