(七十七)地理编码与反地理编码
所谓地理编码,指的是通过地名获取位置信息,例如经纬度、详细地址等。
所谓反地理编码,指的是通过经纬度、海拔等信息获取地理位置信息。
在iOS上使用地理编码和反地理编码,如果是手动输入经纬度,是不需要获取用户授权的,但是一般是获取用户的经纬度,然后再通过地理编码实现精确定位,因此需要授权,本文因为是单独讲解地理编码的相关知识,因此采用手动输人经纬度,不再赘述授权的代码。
①导入框架:
#import <CoreLocation/CoreLocation.h>
②新建CLGeocoder对象:
@property (strong, nonatomic) CLGeocoder *gcoder;
CLGeocoder *coder = [[CLGeocoder alloc] init]; self.gcoder = coder;
【地理编码】
③调用对象的geocodeAddressString:completionHandler方法,传入一个字符串地名,返回的对象为地标数组。一般情况下,地标数组中只有一个元素,通过firstObject或者lastObject得到一个地标。
每个地标都有许多个属性,打印一个地标,可以发现其中的属性过于复杂,其中比较有用的属性还是通过地标类CLPlacemark的头文件,比较重要的列举如下:
location:位置信息,可以得到经纬度、海拔等,上节有介绍。
city:城市名
name:完整地名
addressDictionary:这是一个字典,数据如下
{ City = "\U5317\U4eac\U5e02\U5e02\U8f96\U533a"; Country = "\U4e2d\U56fd"; CountryCode = CN; FormattedAddressLines = ( "\U4e2d\U56fd\U5317\U4eac\U5e02" ); Name = "\U5317\U4eac\U5e02"; State = "\U5317\U4eac\U5e02"; }其中的FormatterAddressLines是格式化的地址,圆括号表示的数组,其中的元素是字符串。
下面的代码把经纬度和格式化的地址获取并输出,self开头的那些成员属性是TextField,用于显示。
NSString *addressStr = self.addressView.text; if(addressStr == nil || addressStr.length == 0){ NSLog(@"请输入地址"); } [self.gcoder geocodeAddressString:addressStr completionHandler:^(NSArray *placemarks, NSError *error) { // 地标数组中存放地标,每一个地标,包含了当前位置的一系列信息。 CLPlacemark *placemark = [placemarks firstObject]; NSLog(@"%@ %@ %f %f",placemark.name, placemark.addressDictionary,placemark.location.coordinate.latitude,placemark.location.coordinate.longitude); self.latiView.text = [NSString stringWithFormat:@"%f",placemark.location.coordinate.latitude]; self.longtiView.text = [NSString stringWithFormat:@"%f",placemark.location.coordinate.longitude]; // addressDictionary中的FormattedAddressLines是一个数组,内部存放的是字符串 NSMutableString *strM = [NSMutableString string]; NSArray *addressLines = placemark.addressDictionary[@"FormattedAddressLines"]; for (NSString *str in addressLines) { [strM appendString:str]; } self.detailView.text = strM; if (error) { NSLog(@"%@",error); } }];
【反地理编码】
④调用reverseGeocodeLocation方法,传入一个CLLocation即可,得到了仍然是地标,和前面一样处理,需要注意的是,CLLocation如果要输入值,要在初始化时设定,因为经纬度、海拔等都是只读属性,因此应当在初始化时赋值,下面的代码通过获取TextField获取经纬度,然后反地理编码得到位置信息:
CLLocationDegrees latitude = [self.latiView.text doubleValue]; CLLocationDegrees longtitude = [self.longtiView.text doubleValue]; CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longtitude]; [self.gcoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) { for (CLPlacemark *placemark in placemarks) { NSLog(@"%@ %@ %f %f",placemark.name, placemark.addressDictionary,placemark.location.coordinate.latitude,placemark.location.coordinate.longitude); self.addressView.text = placemark.addressDictionary[@"City"]; NSMutableString *strM = [NSMutableString string]; NSArray *addressLines = placemark.addressDictionary[@"FormattedAddressLines"]; for (NSString *str in addressLines) { [strM appendString:str]; } self.detailView.text = strM; } if (error) { NSLog(@"%@",error); } }];