Tag: dispatch

  • How to wait until several AFNetworking requests finish

    Use dispatch_group_t, dispatch_group_enter dispatch_group_leave, dispatch_group_notify.

    Also, below is code to send a huge array to server by dividing ti to parts. It is actual when a single request is too big for server – you get “URL too long error” or HTTP 414.

    - (void)divideAndSendContacts:(NSArray *)contactsArray
    {
        [self showSpinner];
        
        dispatch_group_t group = dispatch_group_create();
        
        NSInteger maxContactsInOneRequest = 29;
        NSInteger totalCount = [contactsArray count];
        
        // Округляем в большую сторону по формуле A/B = (A+B-1)/B, например (700 + 300 - 1)/300 = 3.33 = 3.
        NSInteger numberOfParts = (totalCount + maxContactsInOneRequest - 1) / maxContactsInOneRequest;
    
        for (int i = 0; i < numberOfParts; i++) {
            NSRange range = NSMakeRange(i * maxContactsInOneRequest, maxContactsInOneRequest);
            NSInteger lastItemIndex = i * maxContactsInOneRequest + maxContactsInOneRequest; // Например, i=3, 29*3+29=116. Больше 100, поэтому вместо 29 берем 100-29*3=13
            
            if ( lastItemIndex > totalCount ) {
                NSInteger length = totalCount - i * maxContactsInOneRequest;
                range = NSMakeRange(i * maxContactsInOneRequest, length);
            }
            
            NSArray *contactsArrayPart = [contactsArray subarrayWithRange:range];
            
            NSDictionary *contactsDic = @{@"phone_book" : @{@"contacts" : contactsArrayPart}};
            
            dispatch_group_enter(group);
            
            [[SSHTTPClient sharedClient] POST:@"/api/contacts" parameters:contactsDic progress:^(NSProgress * _Nonnull uploadProgress) {
                
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                dispatch_group_leave(group);
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                NSLog(@"Failed method: %@", NSStringFromSelector(_cmd));
                dispatch_group_leave(group);
                
            }];
        }
        
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            
            [self hideSpinner];
            
            [self loadContactsFromServer];
            
        });
        
        return;
    }
    
  • Using dispatch group to wait until multiple operations executed – including completion block (AFNetworking)

    // Загрузка дополнительных данных с сервера по API для форм
    - (void)loadAdditionalInformationFromServer
    {
        loadingError = nil;
        success = YES;
        
        group = dispatch_group_create();
        
        [self startOfferEducationsRetrieveOperation];
        
        [self startOfferLanguageLevelsRetrieveOperation];
        
        [self startOfferTradesRetrieveOperation];
        
        [self startOfferLanguagesRetrieveOperation];
        
        [self startOperatingScheduleRetrieveOperation];
        
        [self startRegionsRetrieveOperation];
        
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
         [self.delegate resumeManagerDidFinishLoadingAdditionalInformationWithSuccess:success error:loadingError];
        });
        
        //dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    
        dispatch_release(group);
    }
    
    
    // Запрос на получение уровней образования
    - (void)startOfferEducationsRetrieveOperation
    {
        if ([[RRSession sharedSession] offerEducations] == nil) {
            
            // Блок успешного завершения запроса
            SuccessBlock successBlock = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                
                NSArray *jsonArray = (NSArray *)JSON;
                NSMutableArray *temp = [NSMutableArray new];
                for (NSDictionary *jsonDic in jsonArray) {
                    RROfferEducation *obj = [[RROfferEducation alloc] initFromDic:jsonDic];
                    [temp addObject:obj];
                }
                [[RRSession sharedSession] setOfferEducations:temp];
                
                dispatch_group_leave(group);
            };
            
            // Добавление запроса на загрузку в очередь
            [self addOperationForMethod:RRApiMethodOfferEducations successBlock:successBlock];
        }
    }
    
    
    // Запрос на получение уровней владения языком
    - (void)startOfferLanguageLevelsRetrieveOperation
    {
        if ([[RRSession sharedSession] offerLanguageLevels] == nil) {
            // Блок успешного завершения запроса
            SuccessBlock successBlock = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                
                NSArray *jsonArray = (NSArray *)JSON;
                NSMutableArray *temp = [NSMutableArray new];
                for (NSDictionary *jsonDic in jsonArray) {
                    RROfferLanguageLevel *obj = [[RROfferLanguageLevel alloc] initFromDic:jsonDic];
                    [temp addObject:obj];
                }
                [[RRSession sharedSession] setOfferLanguageLevels:temp];
                
                dispatch_group_leave(group);
            };
            
            // Добавление запроса на загрузку в очередь
            [self addOperationForMethod:RRApiMethodOfferLanguageLevels successBlock:successBlock];
        }
    }
    
    
    // Запрос на получение языков
    - (void)startOfferLanguagesRetrieveOperation
    {
        if ([[RRSession sharedSession] offerLanguages] == nil) {
            // Блок успешного завершения запроса
            SuccessBlock successBlock = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                
                NSArray *jsonArray = (NSArray *)JSON;
                NSMutableArray *temp = [NSMutableArray new];
                for (NSDictionary *jsonDic in jsonArray) {
                    RROfferLanguage *obj = [[RROfferLanguage alloc] initFromDic:jsonDic];
                    [temp addObject:obj];
                }
                [[RRSession sharedSession] setOfferLanguages:temp];
                
                dispatch_group_leave(group);
            };
            
            // Добавление запроса на загрузку в очередь
            [self addOperationForMethod:RRApiMethodOfferLanguages successBlock:successBlock];
        }
    }
    
    
    // Запрос на получение графиков работы
    - (void)startOperatingScheduleRetrieveOperation
    {
        if ([[RRSession sharedSession] operatingSchedules] == nil) {
            // Блок успешного завершения запроса
            SuccessBlock successBlock = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                
                NSArray *jsonArray = (NSArray *)JSON;
                NSMutableArray *temp = [NSMutableArray new];
                for (NSDictionary *jsonDic in jsonArray) {
                    RROperatingSchedule *obj = [[RROperatingSchedule alloc] initFromDic:jsonDic];
                    [temp addObject:obj];
                }
                [[RRSession sharedSession] setOperatingSchedules:temp];
                
                dispatch_group_leave(group);
            };
            
            // Добавление запроса на загрузку в очередь
            [self addOperationForMethod:RRApiMethodOperatingSchedules successBlock:successBlock];
        }
    }
    
    
    // Запрос на получение регионов
    - (void)startRegionsRetrieveOperation
    {
        if ([[RRSession sharedSession] regions] == nil) {
            // Блок успешного завершения запроса
            SuccessBlock successBlock = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                
                NSArray *jsonArray = (NSArray *)JSON;
                NSMutableArray *temp = [NSMutableArray new];
                for (NSDictionary *jsonDic in jsonArray) {
                    RRRegion *obj = [[RRRegion alloc] initFromDic:jsonDic];
                    [temp addObject:obj];
                }
                [[RRSession sharedSession] setRegions:temp];
                
                dispatch_group_leave(group);
            };
            
            // Добавление запроса на загрузку в очередь
            [self addOperationForMethod:RRApiMethodRegions successBlock:successBlock];
        }
    }
    
    
    // Запрос на получение рубрик вакансий
    - (void)startOfferTradesRetrieveOperation
    {
        if ([[RRSession sharedSession] offerTrades] == nil) {
            // Блок успешного завершения запроса
            SuccessBlock successBlock = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                
                NSArray *jsonArray = (NSArray *)JSON;
                NSMutableArray *temp = [NSMutableArray new];
                for (NSDictionary *jsonDic in jsonArray) {
                    RROfferTrade *obj = [[RROfferTrade alloc] initFromDic:jsonDic];
                    [temp addObject:obj];
                }
                [[RRSession sharedSession] setOfferTrades:temp];
                
                dispatch_group_leave(group);
            };
            
            // Добавление запроса на загрузку в очередь
            [self addOperationForMethod:RRApiMethodOfferTrades successBlock:successBlock];
        }
    }
    
    
    // Добавление запроса на загрузку в очередь
    - (void)addOperationForMethod:(NSString *)methodName successBlock:(SuccessBlock)successBlock
    {
        dispatch_group_enter(group);
        
        RRHTTPClient *client = [RRHTTPClient sharedClient];
        NSString *apiMethodPath = [NSString stringWithFormat:@"%@%@", [RRHelper apiDomain], methodName];
        NSMutableURLRequest *request = [client requestWithMethod:@"GET" path:apiMethodPath parameters:nil];
        AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:successBlock failure:[self getStandartFailureBlock]];
        [operation start];
        
        //[[RRServerConnection sharedConnection] addCustomOperation:operation];
    }
    
    
    // Блок обработки ошибки при запросе
    - (FailureBlock)getStandartFailureBlock
    {
        FailureBlock failureBlock = ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
            
            success = NO;
            loadingError = error;
            
            NSLog(@"Error: %@", error);
            [RRHelper showServerErrorMessage];
            
            dispatch_group_leave(group);
            
        };
        
        return failureBlock;
    }