HariNarasimhaRao.G
HariNarasimhaRao.G

Reputation: 41

How to wait for the callBack methods (or) response in for loop (Xcode, Objective C, iOS)?

In my code i have multiple locations,I have to check all the locations are correct or not (checking with google api) if location is correct I have to get the coordinates for that location.

I am trying to write the code in for loop is there any way to wait for the response in the for loop.

I am pasting my code below.

thanks in Advance.

for (int locationsCount=0;locationsCount<results.count;locationsCount++)
    {
        NSString *googlelocations = [[results objectAtIndex:locationsCount]objectForKey:@"description"];

        if ([locationAddress isEqualToString:googlelocations])
        {
            [[LocationManager share] fetchLatLngForPlacename:googlelocations placeId:[[results objectAtIndex:locationsCount] objectForKey:@"place_id"] completion:^(double lat, double lng, NSError *error)
            {
                [SVProgressHUD dismiss];

                if (error) {

                }else {

                    CLLocation *locationCoordinates = [[CLLocation alloc]initWithLatitude:lat longitude:lng];

                    NSMutableArray *globalArray = [[LocationManager share]getManualInterLocationArray];
                    NSMutableDictionary *dict = [[globalArray objectAtIndex:selectedTextField.tag] mutableCopy];

                    [dict setObject:locationCoordinates forKey:@"location_coordinates"];

                    [dict setObject:googlelocations forKey:@"location_Address"];

                    [dict setObject:[NSNumber numberWithBool:true] forKey:@"manualEntry_Flag"];

                    [globalArray replaceObjectAtIndex:selectedTextField.tag withObject:dict];

                    [[LocationManager share]saveManualInterLocationArray:globalArray];

                }

            }];
        }
    }

Upvotes: 0

Views: 1712

Answers (3)

HariNarasimhaRao.G
HariNarasimhaRao.G

Reputation: 41

I used the recursive method for this requirement it's working fine now. Recursive method is the best and easy way to fulfil this requirement.

-(void)addressValidation:(int)locationCount andCompletion:(void(^)(BOOL isSuccess))callBack{
if (manualarraycount >= globalArray.count)
{
    callBack(true);
    return;
}

[[LocationManager share] fetchOfflineAutoCompleteSuggestionForKey:locationAddress LocationCoordinates:location Radius:duration completion:^(NSArray *results, NSError *error){
    // --------- do what you want ------------
    [self addressValidation:manualarraycount+1 andCompletion:callBack];
}];

}

Upvotes: 1

Gerd K
Gerd K

Reputation: 2993

A dispatch group can be used, like in this pseudo code:

dispatch_group_t loadDetailsGroup=dispatch_group_create();

for(id thing in thingsToDo)
{
    dispatch_group_enter(loadDetailsGroup);

    // call method with completion callback, and in the callback run
    dispatch_group_leave(loadDetailsGroup);
}

// Now outside the loop wait until everything is done. NOTE: this will block!
dispatch_group_wait(loadDetailsGroup, DISPATCH_TIME_FOREVER);

If you are running this on the main thread, you should not block it so the UI remains responsive. So you could do the wait part in the background, then possibly do something in the main thread when done:

// to background 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
    // wait in background
    dispatch_group_wait(loadDetailsGroup, DISPATCH_TIME_FOREVER);

    // back to main (not needed if what you need to do may happen in background)
    dispatch_async(dispatch_get_main_queue(),^{

        // do stuff here that affects the UI
    });
});

Edit: As Kurt Revis pointed out, if you want to wait asynchronously and have a callback, dispatch_group_notify() is better suited for that. So the entire above code could be condensed to:

dispatch_group_t loadDetailsGroup=dispatch_group_create();

for(id thing in thingsToDo)
{
    dispatch_group_enter(loadDetailsGroup);

    // call method with completion callback, and in the callback run
    dispatch_group_leave(loadDetailsGroup);
}

// Now outside the loop wait until everything is done. NOTE: this will
// not block execution, the provided block will be called
// asynchronously at a later point.
dispatch_group_notify(loadDetailsGroup,dispatch_get_main_queue(),^{

    // Callback
});

Upvotes: 0

iamirzhan
iamirzhan

Reputation: 954

Try to use recursion. Create a function

-(void)setLocation:(NSUInteger)locationCount andCompletion:(void (^))completionBlock{
    if (locationsCount>=results.count) {
       if (completion) {
              completion();
       }
       return;
    }
    NSString *googlelocations = [[results objectAtIndex:locationsCount]objectForKey:@"description"];

    if ([locationAddress isEqualToString:googlelocations])
    {
        [[LocationManager share] fetchLatLngForPlacename:googlelocations placeId:[[results objectAtIndex:locationsCount] objectForKey:@"place_id"] completion:^(double lat, double lng, NSError *error)
        {
            [SVProgressHUD dismiss];

            if (error) {

            }else {

                CLLocation *locationCoordinates = [[CLLocation alloc]initWithLatitude:lat longitude:lng];

                NSMutableArray *globalArray = [[LocationManager share]getManualInterLocationArray];
                NSMutableDictionary *dict = [[globalArray objectAtIndex:selectedTextField.tag] mutableCopy];

                [dict setObject:locationCoordinates forKey:@"location_coordinates"];

                [dict setObject:googlelocations forKey:@"location_Address"];

                [dict setObject:[NSNumber numberWithBool:true] forKey:@"manualEntry_Flag"];

                [globalArray replaceObjectAtIndex:selectedTextField.tag withObject:dict];

                [[LocationManager share]saveManualInterLocationArray:globalArray];

            }

        }];
    }
}

In your completion block call the function itself with increment count:

[self setLocation:locationCount++ andCompletion:nil];

And to start your repeating call the function where you need starting from 0

[self setLocation:0 andCompletion:^{
 // handle completion
 }];

Upvotes: 0

Related Questions