0

У меня есть метод с двумя вызовами завершения и вы хотите вызвать блок dispatch_group_notify после этого. Это работает после первого завершения, но не после второго. Мне нужно, чтобы это работало после второго звонка.dispatch_group_notify после второго вызова завершения

Вот мой код:

method1WithCompletion: и method2WithCompletion: будет иметь 2 ответов, во-первых, что будет с локальными данными, а затем делает запрос на апи и возвращать данные 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 
}); 

не конечно, как правильно настроить

+0

Вы хотите сказать, что этот блок завершения будет вызываться дважды для каждого вызова? Что именно вы подразумеваете под «Я получу 2 ответа»? – Rob

ответ

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

 Смежные вопросы

  • Нет связанных вопросов^_^