• (七十七)地理编码与反地理编码


    所谓地理编码,指的是通过地名获取位置信息,例如经纬度、详细地址等。

    所谓反地理编码,指的是通过经纬度、海拔等信息获取地理位置信息。

    在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 = "U5317U4eacU5e02U5e02U8f96U533a";
        Country = "U4e2dU56fd";
        CountryCode = CN;
        FormattedAddressLines =     (
            "U4e2dU56fdU5317U4eacU5e02"
        );
        Name = "U5317U4eacU5e02";
        State = "U5317U4eacU5e02";
    }
    其中的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);
            }
        }];

  • 相关阅读:
    一元运算符重载 前置和后置++ --(这种一般用成员函数来实现重载)
    运算符中的二元重载,为什么要调用友元函数而不是全局函数的问题
    关于数组的封装不知道为什么错了,具体代码如下
    关于对象的动态建立和释放
    关于构造函数中调用构造函数的危险
    关于析构函数,构造函数匿名对象的总结,以厚忘了,可以回来观看很全
    关于深拷贝和浅拷贝的疑问
    构造函数的调用大全
    构造函数的调用(其中不包括赋值构造函数)
    LeetCode:Add Digits
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154125.html
Copyright © 2020-2023  润新知