dispatch_async in return method Objective-C
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.
Santosh Gurram
Updated on June 08, 2022Comments
-
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 thedispatch_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 ofisContactExistsInXYZ
is not what I expect. How do I handledispatch_async
in this situation? -
Santosh Gurram over 10 yearsCan u elaborate with a sample code or are you saying me to use "completion handler" block
-
Santosh Gurram over 10 yearsHere 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
overdispatch_sync
. Can you please get me a logical information or to handle the same in other way. Thanks. -
Abhinav over 10 yearsYou 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.