【问题标题】:How to wait for the callBack methods (or) response in for loop (Xcode, Objective C, iOS)?如何在 for 循环(Xcode、Objective C、iOS)中等待回调方法(或)响应?
【发布时间】:2017-06-15 13:09:18
【问题描述】:

在我的代码中,我有多个位置,我必须检查所有位置是否正确(使用 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];

                }

            }];
        }
    }

【问题讨论】:

    标签: ios objective-c xcode objective-c-blocks


    【解决方案1】:

    我为这个需求使用了递归方法,它现在工作正常。递归方法是满足此要求的最佳且简单的方法。

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

    }

    【讨论】:

      【解决方案2】:

      尝试使用递归。创建函数

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

      【讨论】:

      • 我希望该方法被回调。有可能吗?
      • 上述方法是由回调函数调用的,所以在完成该过程后我们必须发送确认以继续下一个过程。 -(void)validateAllAddressesinManualArray:(void(^)(BOOL isSuccess))callBack { if (appDelegate().internetSatus == false) { return; } 地址数组计数=0; [self addressValidation:addressArrayCount andCompletion:^(BOOL isSuccess) { if (isSuccess) { callBack(true); NSLog(@"完成"); } }]; }
      【解决方案3】:

      可以使用调度组,就像下面的伪代码:

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

      【讨论】:

      • 在您的第二个代码块中,改为dispatch_group_notify(loadDetailsGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ... }); 不是更直接吗?这样你就可以避免在队列中等待一个块。
      猜你喜欢
      • 2019-07-18
      • 1970-01-01
      • 2015-09-10
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-27
      相关资源
      最近更新 更多