Waiting until two async blocks are executed before starting another block
Use dispatch groups: see here for an example, "Waiting on Groups of Queued Tasks" in the "Dispatch Queues" chapter of Apple's iOS Developer Library's Concurrency Programming Guide
Your example could look something like this:
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block1
NSLog(@"Block1");
[NSThread sleepForTimeInterval:5.0];
NSLog(@"Block1 End");
});
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block2
NSLog(@"Block2");
[NSThread sleepForTimeInterval:8.0];
NSLog(@"Block2 End");
});
dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block3
NSLog(@"Block3");
});
// only for non-ARC projects, handled automatically in ARC-enabled projects.
dispatch_release(group);
and could produce output like this:
2012-08-11 16:10:18.049 Dispatch[11858:1e03] Block1
2012-08-11 16:10:18.052 Dispatch[11858:1d03] Block2
2012-08-11 16:10:23.051 Dispatch[11858:1e03] Block1 End
2012-08-11 16:10:26.053 Dispatch[11858:1d03] Block2 End
2012-08-11 16:10:26.054 Dispatch[11858:1d03] Block3
Waiting until the task finishes
Use DispatchGroup
s to achieve this. You can either get notified when the group's enter()
and leave()
calls are balanced:
func myFunction() {
var a: Int?
let group = DispatchGroup()
group.enter()
DispatchQueue.main.async {
a = 1
group.leave()
}
// does not wait. But the code in notify() gets run
// after enter() and leave() calls are balanced
group.notify(queue: .main) {
print(a)
}
}
or you can wait:
func myFunction() {
var a: Int?
let group = DispatchGroup()
group.enter()
// avoid deadlocks by not using .main queue here
DispatchQueue.global(attributes: .qosDefault).async {
a = 1
group.leave()
}
// wait ...
group.wait()
print(a) // you could also `return a` here
}
Note: group.wait()
blocks the current queue (probably the main queue in your case), so you have to dispatch.async
on another queue (like in the above sample code) to avoid a deadlock.
at point dispatch_group_async considers the task done when it is executing async task with callbacks
If you dispatch an asynchronous task, say "task B", inside a dispatch_group_async
, say "Task A" then Task A will be considered complete as soon as the end of the Task A block is reached even though Task B may still be executing.
So, given
dispatch_async_group(group,queue, ^{
[someAsyncTask B];
});
dispatch_async_group(group,queue, ^{
[someAsyncTask C];
});
dispatch_async_group(group,queue, ^{
[someAsyncTask D];
});
dispatch_group_wait(group,10000);
The dispatch_group_wait
will return as soon as the final dispatch_async_group
block finishes executing even though tasks B/C/D may still be running.
If you use synchronous dispatch for tasks B/C/D then your dispatch group will be considered complete after B,C & D finish.
Wait for block of code before running second Swift
Alamofire.request
is an asynchronous call so it will return right away and therefore your method getVersion
will return right away. You need to make getVersion
method wait until Alamofire.request
completes the call and versionarray is updated before continuing.
Waiting for asynchronously-executed block to finish
At the point where your NSLog line is run, your completion block has not yet been called. reverseGeocodeLocation is a non-blocking call, which is why it takes a completion handler.
What you DON'T want to do is to turn this into a synchronous method. I presume you want to update your UI in response to the geocode completing. Do something like this:
I don't see what the "[placemarks copy]" line is supposed to achieve. It's completely pointless because you're ignoring the return value.
[deviceInfo.geocoder reverseGeocodeLocation:deviceInfo.locationProperties completionHandler:
^(NSArray *placemarks, NSError *error) {
[placemarks copy];
//Get nearby address
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(@"Country : %@",placemark.country);
// No need for response to be a __block variable.
NSString *response =placemark.country;
dispatch_async(dispatch_get_main_queue(), ^{
[self updateUIWithResponse:response];
}
];
-(void)updateUIWithResponse:(NSString*)response
{
NSLog(@"Got a response: %@), response);
}
Related Topics
How to Enable Native Resolution For Apps on Iphone 6 and 6 Plus
Opening the Settings App from Another App
How to Find Current Visible Viewcontroller in Ios
Save Generated Gif to Camera Roll
How to Exit Iphone Application
How to Debug 'Unrecognized Selector Sent to Instance' Error
Undefined Symbols For Architecture Armv7
What Happens When Testflight App Expire
How to Change Button Title Alignment in Swift
Iphone 6 and 6 Plus Media Queries
Attempt to Present Uiviewcontroller on Uiviewcontroller Whose View Is Not in the Window Hierarchy
How to Check For an Active Internet Connection on iOS or Macos
Loading/Downloading Image from Url on Swift
Draw Text Along Circular Path in Swift For Ios
Iphone/Ipad: How to Make Uitextfield Readonly (But Not Disabled)