对用于反向地理编码位置的 CLGeocoder 类方法感到困惑

Posted

技术标签:

【中文标题】对用于反向地理编码位置的 CLGeocoder 类方法感到困惑【英文标题】:Confused about CLGeocoder class method for reverse geocoding a location 【发布时间】:2013-12-24 02:54:58 【问题描述】:

在过去的 2 个小时里,我一直在努力实现用于对位置进行反向地理编码的 CLGeocoder 类方法。

Xcode 文档中 CLGeocode 类参考下为此方法提供的代码如下:

- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler

我试图在我的代码中使用它并且没有任何运气。所以我查看了一些旧的 *** 问题,并找到了一个最终为我工作的实现。

这是适合我的代码:

-(IBAction)gpsButton 

 CLGeocoder *geocoder = [[CLGeocoder alloc]init];

 [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error)

  CLPlacemark *placemark = placemarks[0];
  NSLog(@"Found %@", placemark.thoroughfare);



 ];


我不明白为什么 xcode 文档包含 (CLLocation *) 和 (CLGeocodeCompletionHandler),而这并不是最终代码真正需要的样子。

是否只是想提醒我“位置”对象应该是 CLLocation 类的实例,而“completionHandler”对象应该是 CLGeocodeCompletionHandler 类的实例?

是不是想提醒我,在实现此方法之前,我需要为 CLLocation 类和 CLGeocodeCompletionHandler 类创建和初始化对象,以便该方法可以正常运行?如果是这种情况,那么为什么 CLLocation 在 xcode 示例中有一个指针,而 CLGeocodeCompletionHandler 没有?

我意识到这是一个“基础”类型的问题,但我已经查看了一些我的首选参考资料,他们解释事物的方式确实无法帮助我解决当前的困惑。

感谢您的帮助。

【问题讨论】:

【参考方案1】:

你说:

我不明白为什么 xcode 文档包含 (CLLocation *) 和 (CLGeocodeCompletionHandler),而这并不是最终代码真正需要的样子。

问题是,这最终代码的样子。因此,正如您所指出的,reverseGeocodeLocation:completionHandler: 方法的定义如下:

- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;

此外,如果您查看CLGeocodeCompletionHandler 的定义,它被定义为一个返回void 并接受两个参数的块,一个地标数组和一个NSError 对象,如下所示:

typedef void (^CLGeocodeCompletionHandler)(NSArray *placemarks, NSError *error);

因此,下面的代码示例完全符合此定义:

[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error)

    CLPlacemark *placemark = placemarks[0];
    NSLog(@"Found %@", placemark.thoroughfare);

];

如果你问为什么reverseGeocodeLocation:completionHandler: 的方法定义使用CLGeocodeCompletionHandler typedef,而不是实际的复杂块定义,他们这样做是为了简化代码。是的,它使 Xcode 的“代码补全”变得不那么有用,但是当您实际编写使用 block 参数实现此方法的代码时,它会让您的生活变得更加轻松。

当您开始编写自己的方法来获取块参数并拥有将这些块存储在属性中的类时,您会发现使用typedef 确实是天赐之物,消除了许多由拼写错误导致的简单错误非常尴尬的块语法。

例如,假设您想将该块保存在一个变量中,然后在对reverseGeocodeLocation 的调用中使用该变量。因为你有一个 typedef,所以很简单:

CLGeocodeCompletionHandler customHandler = ^(NSArray *placemarks, NSError *error)
    CLPlacemark *placemark = placemarks[0];
    NSLog(@"Found %@", placemark.thoroughfare);
;

[geocoder reverseGeocodeLocation:currentLocation completionHandler:customHandler];

如果没有 typedef,您将不得不求助于稍微笨拙的语法:

void (^customHandler)(NSArray *, NSError *) = ^void(NSArray *placemarks, NSError *error) 
    CLPlacemark *placemark = placemarks[0];
    NSLog(@"Found %@", placemark.thoroughfare);
;

[geocoder reverseGeocodeLocation:currentLocation completionHandler:customHandler];

诚然,这是一个有些人为的例子,但是随着您越来越多地使用块,您将开始欣赏typedef 提供的简单性,因为您必须在整个过程中一次又一次地使用相同的块签名代码。

所以,每当您看到一个方法有一个自定义块 typedef 作为参数时,只需再深入一层细节,然后查看 typedef,一切都会变得清晰。

【讨论】:

再完美不过了。谢谢!【参考方案2】:

CLLocation 是你需要初始化和 reverseGeocode 的类,但 CLGeocodeCompletionHandler 是块类型定义句柄的回调。所以你不必初始化它。

【讨论】:

为什么我不必初始化 CLGeocodeCompletionHandler 背后的理论是什么?就因为它是一个typedef,因为它是一个block,因为它是一个block typedef? 块是函数指针,不是类。阅读Block Guide 简单地说,块是一段作为变量传递的代码。因此,您可以说“做一些事情然后运行这个块”,而不是一个典型的方法说“用这个 NSString 做这个”。您通常 typedef 块以便更容易地引用它们(从语法中可以看出,声明一个块在语法上是乏味的)。 谢谢你。你用简单明了的英语解释的方式真的很有帮助。

以上是关于对用于反向地理编码位置的 CLGeocoder 类方法感到困惑的主要内容,如果未能解决你的问题,请参考以下文章

CLGeocoder 反向地理编码位置。第一次在 [placemarks count = 0]?

CLGeocoder 反向地理编码失败,错误域=NSURLErrorDomain 代码=-1000 -

在 iOS 中使用 CLGeocoder 进行转发地理编码,为某些位置的位置返回 null

如何在 iOS 中使用反向谷歌地理编码?

CLLocationManager 和 CLGeoCoder

对许多地址进行地理编码 - CLGeocoder