0

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

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

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

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

这是对我有用的代码:

-(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没有呢?

我意识到这是一个“基本面”类型的问题,但我已经阅读了一些我的首选参考资料,他们解释事情的方式并没有帮助我解决当前的困惑。

感谢您的帮助。

4

2 回答 2

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:使用CLGeocodeCompletionHandlertypedef,而不是实际的复杂块定义,他们这样做是为了简化代码。是的,它使 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,一切都会变得清晰。

于 2013-12-24T04:35:11.417 回答
0

那么CLLocation是你需要初始化和 reverseGeocode 的类,但CLGeocodeCompletionHandler它是一个块 typedef 句柄的回调。所以你不必初始化它。

于 2013-12-24T03:01:24.910 回答