如何在 for 循环 (Xcode、Objective C、iOS) 中等待回调方法(或)响应?

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

在我的代码中我有多个位置,我必须检查所有位置是否正确(使用 google api 检查)如果位置正确我必须获得坐标位置。

我正在尝试在for循环中编写代码,有什么方法可以在for循环中等待响应。

我在下面粘贴我的代码。

提前致谢。

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

                }

            }];
        }
    }

尝试使用递归。创建函数

-(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];

            }

        }];
    }
}

在您的完成块中使用增量计数调用函数本身:

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

并开始重复调用您需要从 0 开始的函数

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

可以使用调度组,就像在这个伪代码中:

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

如果您 运行 在主线程上执行此操作,则不应阻止它,以便 UI 保持响应。所以你可以在后台做等待部分,然后在完成后可能在主线程中做一些事情:

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

编辑: 正如 Kurt Revis 指出的那样,如果您想异步等待并进行回调,dispatch_group_notify() 更适合。所以上面的整个代码可以浓缩为:

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

我对这个要求使用了递归方法,现在工作正常。递归方法是满足这一要求的最好和最简单的方法。

-(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];
}];

}