【问题标题】:Storing the values from completion handler into a variable将完成处理程序中的值存储到变量中
【发布时间】:2014-04-09 03:30:24
【问题描述】:

我试图在完成处理程序中存储一个字符串值,但它的范围仅限于该块。如何解决?

// Do any additional setup after loading the view, typically from a nib.
    CLLocationManager *locationManager = [[CLLocationManager alloc] init];
    locationManager.distanceFilter = kCLDistanceFilterNone;
    locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
    [locationManager startUpdatingLocation];


    CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
    NSString *co;
    [geocoder reverseGeocodeLocation:locationManager.location
                   completionHandler:^(NSArray *placemarks, NSError *error) {
                       NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");

                       if (error){
                           NSLog(@"Geocode failed with error: %@", error);
                           return;

                       }


                       CLPlacemark *placemark = [placemarks objectAtIndex:0];



                       NSLog(@"placemark.country %@",placemark.country);
                       co = placemark.country;
                       // 
                   }];

    NSLog(@"%@",co);

在这一行,co 的值再次变为 null。请告诉我,如何在完成处理程序之外保留值,我将其存储在完成处理程序中。

【问题讨论】:

  • 尝试co = placemark.country;, co = [co copy];
  • 不,那样不行!
  • 在 NSString *co; 之前添加 __block;

标签: ios block local-variables


【解决方案1】:

问题不是范围问题,而是在完成块之前调用日志。反向地理编码调用是异步的。每当它完成它正在做的事情时,它将返回该块,但与此同时,您的方法的其余部分将执行。如果在设置其值后但在完成块内打印该行,它将显示正确的值。

例子:

[geocoder reverseGeocodeLocation:locationManager.location
               completionHandler:^(NSArray *placemarks, NSError *error) {
                   NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");

                   if (error){
                       NSLog(@"Geocode failed with error: %@", error);
                       return;

                   }


                   CLPlacemark *placemark = [placemarks objectAtIndex:0];



                   NSLog(@"placemark.country %@",placemark.country);
                   co = placemark.country;

                   // The completion block has returned and co has been set. The value equals placemark.country
                   NSLog(@"%@",co);
               }];
// This log is executed before the completion handler. co has not yet been set, the value is nil
NSLog(@"%@",co);

如果你需要在块外使用 co 变量,你应该在完成块内调用它将被使用的方法:

[geocoder reverseGeocodeLocation:locationManager.location
               completionHandler:^(NSArray *placemarks, NSError *error) {

    [self myMethodWithCountry:placemark.country];

}];

- (void)myMethodWithCountry:(NSString *)country {
    // country == placemark.country
}

【讨论】:

    【解决方案2】:

    您编写的NSLog 命令将在您完成该块之前运行。由于发生这种情况,您将获得null。您可以做的一件事是在块内打印co 的值,而不是在外面打印。

    修改co的声明如下:

     __block NSString *co= nil; 
    

    【讨论】:

      【解决方案3】:

      按照 Julie 的建议,在 NSString *co; 之前添加 __block,即 __block NSString *co;。顺便说一句,这是两个下划线。

      【讨论】:

      • 好吧,它仍然无法存储该值。我想把它写在一个返回 (NSString *) 的函数中
      • @NileshAgrawal ARC 已禁用
      • 是的,它已被禁用。但是也启用它之后,我无法获得它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-22
      • 1970-01-01
      相关资源
      最近更新 更多