第二次完成调用后dispatch_group_notify

时间:2015-12-02 07:31:49

标签: ios multithreading grand-central-dispatch nsoperation dispatch

我有两个完成调用的方法,并希望在此之后调用dispatch_group_notify块。这在第一次完成后有效,但在第二次完成后无效。我需要在第二次通话后才能使用。

这是我的代码:

method1WithCompletion:和method2WithCompletion:将有2个响应,首先是本地数据,后来发出请求api并返回api数据

  dispatch_group_t requestGroup = dispatch_group_create();

  dispatch_group_enter(requestGroup);
 [self method1WithCompletion:^(NSArray *items) {
//here I will get 2 responses (first from local storage, second from api)
dispatch_group_leave(requestGroup);
 }];

  dispatch_group_enter(requestGroup);
 [self method2WithCompletion:^(NSArray *items) {
//here I will get 2 responses (first from local storage, second from api)
dispatch_group_leave(requestGroup);
 }];

 // now this will only be called once the two "enter" calls are balanced with the corresponding "leave" calls

 dispatch_group_notify(requestGroup, dispatch_get_main_queue(), ^{
//completion
//that should be called after method 1 and method 2 executed with local data,           and after they executed with api data
 });

不确定如何正确设置

1 个答案:

答案 0 :(得分:0)

据我所知,这些完成块将被调用两次,一次用于本地数据,第二次用于API数据。并且您希望在两个本地调用完成时调用通知块,并在两个API调用完成时再次调用。

为此,您需要两个调度组,您可以执行以下操作:

dispatch_group_t requestGroupLocal = dispatch_group_create();
dispatch_group_t requestGroupAPI = dispatch_group_create();

dispatch_group_enter(requestGroupLocal);
dispatch_group_enter(requestGroupAPI);
__block NSInteger count1 = 0;
[self method1WithCompletion:^(NSArray *items) {
    if (count1 == 0) {
        dispatch_group_leave(requestGroupLocal);
        count1++;
    } else {
        dispatch_group_leave(requestGroupAPI);
    }
}];

dispatch_group_enter(requestGroupLocal);
dispatch_group_enter(requestGroupAPI);
__block NSInteger count2 = 0;
[self method2WithCompletion:^(NSArray *items) {
    if (count2 == 0) {
        dispatch_group_leave(requestGroupLocal);
        count2++;
    } else {
        dispatch_group_leave(requestGroupAPI);
    }
}];

dispatch_block_t completion = ^{
    // do whatever you want when each group finishes
};

dispatch_group_notify(requestGroupLocal, dispatch_get_main_queue(), completion);
dispatch_group_notify(requestGroupAPI, dispatch_get_main_queue(), completion);

或者,更好的是,您可以在块中添加一个参数来指示它是否是本地呼叫,而不是依赖于那些神秘的计数器:

dispatch_group_t requestGroupLocal = dispatch_group_create();
dispatch_group_t requestGroupAPI = dispatch_group_create();

dispatch_group_enter(requestGroupLocal);
dispatch_group_enter(requestGroupAPI);
[self method1WithCompletion:^(NSArray *items, BOOL isLocal) {
    if (isLocal) {
        dispatch_group_leave(requestGroupLocal);
    } else {
        dispatch_group_leave(requestGroupAPI);
    }
}];

dispatch_group_enter(requestGroupLocal);
dispatch_group_enter(requestGroupAPI);
[self method2WithCompletion:^(NSArray *items, BOOL isLocal) {
    if (isLocal) {
        dispatch_group_leave(requestGroupLocal);
    } else {
        dispatch_group_leave(requestGroupAPI);
    }
}];

dispatch_block_t completion = ^{
    // do whatever you want when each group finishes
};

dispatch_group_notify(requestGroupLocal, dispatch_get_main_queue(), completion);
dispatch_group_notify(requestGroupAPI, dispatch_get_main_queue(), completion);

坦率地说,这种两次调用完成处理程序的模式非常不典型,并且有点怀疑。我可以想象当前设计背后的意图,但我倾向于退休。相反,我宁愿看到本地和API再现的单独方法,只能调用它们的完成处理程序一次:

dispatch_group_t requestGroupLocal = dispatch_group_create();

dispatch_group_enter(requestGroupLocal);
[self methodLocal1WithCompletion:^(NSArray *items) {
    dispatch_group_leave(requestGroupLocal);
}];

dispatch_group_enter(requestGroupLocal);
[self methodLocal2WithCompletion:^(NSArray *items) {        
    dispatch_group_leave(requestGroupLocal);
}];

dispatch_group_t requestGroupAPI = dispatch_group_create();

dispatch_group_enter(requestGroupAPI);
[self methodAPI1WithCompletion:^(NSArray *items) {        
    dispatch_group_leave(requestGroupAPI);
}];

dispatch_group_enter(requestGroupAPI);
[self methodAPI2WithCompletion:^(NSArray *items) {        
    dispatch_group_leave(requestGroupAPI);
}];

dispatch_block_t completion = ^{
    // do whatever you want when each group finishes
};

dispatch_group_notify(requestGroupLocal, dispatch_get_main_queue(), completion);
dispatch_group_notify(requestGroupAPI, dispatch_get_main_queue(), completion);

或者,如果你真的只想要方法1和2的一个方法,那么使local成为一个参数,但同样,只写一次调用它们的完成处理程序的方法:

dispatch_group_t requestGroupLocal = dispatch_group_create();

dispatch_group_enter(requestGroupLocal);
[self method1Local:true completion:^(NSArray *items) {
    dispatch_group_leave(requestGroupLocal);
}];

dispatch_group_enter(requestGroupLocal);
[self method2Local:true completion:^(NSArray *items) {
    dispatch_group_leave(requestGroupLocal);
}];

dispatch_group_t requestGroupAPI = dispatch_group_create();

dispatch_group_enter(requestGroupAPI);
[self method1Local:false completion:^(NSArray *items) {
    dispatch_group_leave(requestGroupAPI);
}];

dispatch_group_enter(requestGroupAPI);
[self method2Local:false completion:^(NSArray *items) {
    dispatch_group_leave(requestGroupAPI);
}];

dispatch_block_t completion = ^{
    // do whatever you want when each group finishes
};

dispatch_group_notify(requestGroupLocal, dispatch_get_main_queue(), completion);
dispatch_group_notify(requestGroupAPI, dispatch_get_main_queue(), completion);