This is my first time using dispatch_group_t
and I'm making a simple mistake. dispatch_group_notify
is getting called before any of the async calls are returning therefore before even the first dispatch_group_leave(group)
, which then throws a EXC_BAD_INSTRUCTION
.
However, I don't know why this is happening.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[self getCategoriesMainWithParameters:nil withSuccess:^(NSArray *objects) {
[categoriesMain addObjectsFromArray:objects];
dispatch_group_leave(group);
} failure:^(NSError *error) {
groupError = error;
dispatch_group_leave(group);
}];
});
dispatch_group_async(group, queue, ^{
[self getCategoriesSubWithParameters:nil withSuccess:^(NSArray *objects) {
[categoriesSub addObjectsFromArray:objects];
dispatch_group_leave(group);
} failure:^(NSError *error) {
groupError = error;
dispatch_group_leave(group);
}];
});
dispatch_group_async(group, queue, ^{
[self getCategoriesProductWithParameters:nil withSuccess:^(NSArray *objects) {
[categoriesProduct addObjectsFromArray:objects];
dispatch_group_leave(group);
} failure:^(NSError *error) {
groupError = error;
dispatch_group_leave(group);
}];
});
dispatch_group_notify(group,dispatch_get_main_queue(),^{
...
});
The function dispatch_group_async
automatically “enters” the group when the block is dispatched, and automatically “leaves” when the dispatched block finishes. But you are calling dispatch_group_leave
again, so you end up with too many “leave” calls, resulting in the error you describe.
One should either call dispatch_group_async
(with all the “enter” and “leave” calls made for you), or manually call dispatch_group_enter
before the async call and calling dispatch_group_leave
in the completion handler of the asynchronous process.
In this case, because you are calling an asynchronous task inside the dispatched block, the dispatch_group_async
pattern won’t work. You want to manually dispatch_group_enter
before calling the asynchronous method and then having the completion handler call dispatch_group_leave
, as you have. The group will be notified when every “enter” is matched by a “leave”. And because the method that you are calling is already asynchronous, you don’t need to use dispatch_async
or dispatch_group_async
at all.
Thus, it might look like:
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[self getCategoriesMainWithParameters:nil withSuccess:^(NSArray *objects) {
[categoriesMain addObjectsFromArray:objects];
dispatch_group_leave(group);
} failure:^(NSError *error) {
groupError = error;
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[self getCategoriesSubWithParameters:nil withSuccess:^(NSArray *objects) {
[categoriesSub addObjectsFromArray:objects];
dispatch_group_leave(group);
} failure:^(NSError *error) {
groupError = error;
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[self getCategoriesProductWithParameters:nil withSuccess:^(NSArray *objects) {
[categoriesProduct addObjectsFromArray:objects];
dispatch_group_leave(group);
} failure:^(NSError *error) {
groupError = error;
dispatch_group_leave(group);
}];
dispatch_group_notify(group,dispatch_get_main_queue(),^{
...
});