zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

iOS小技能:地理编码(地址转坐标)

ios编码地址 技能 坐标 地理
2023-06-13 09:11:18 时间

前言

需求:手动输入位置信息需要进行地理编码获取经纬度,判断是否为国内地址。

I 高德位置服务:地理编码(地址转坐标)

用户在高德地图官网申请Web服务API类型Key:https://lbs.amap.com/dev/

开发 > Web服务 API > 开发指南 > API文档 > 地理/逆地理编码 :https://lbs.amap.com/api/webservice/guide/api/georegeo/

1.1地理编码 API 服务地址

  • https://restapi.amap.com/v3/geocode/geo?parameters

商户进件→商户详情,重新定位,若输入的地址只有国家+市(例如:中国浙江),点击确定后,去请求第三方地理编码信息(高德API)的时候会转换失败,获取不到经纬度信息。提示:【获取经纬度失败,请输入详细地址!】

1.2适用场景

  • 地理编码:将手动输入的详细的结构化地址转换为高德经纬度坐标。且支持对地标性名胜景区、建筑物名称解析为高德经纬度坐标。1、结构化地址举例:北京市朝阳区阜通东大街6号转换后经纬度:116.480881,39.989410 2、地标性建筑举例:天安门转换后经纬度:116.397499,39.908722
  • 逆地理编码:将经纬度转换为详细结构化的地址,且返回附近周边的POI、AOI信息。1、例如:116.480881,39.989410 转换地址描述后:北京市朝阳区阜通东大街6号

1.3 结构化地址信息 address请求参数的要求

  • 规则遵循:国家、省份、城市、区县、城镇、乡村、街道、门牌号码、屋邨、大厦,如:北京市朝阳区阜通东大街6号。
  • 另外这个API的对地址的具体要求是:结构化地址的定义:首先,地址肯定是一串字符,内含国家、省份、城市、区县、城镇、乡村、街道、门牌号码、屋邨、大厦等建筑物名称。按照由大区域名称到小区域名称组合在一起的字符。一个有效的地址应该是独一无二的。注意:针对大陆、港、澳地区的地理编码转换时可以将国家信息选择性的忽略,但省、市、城镇等级别的地址构成是不能忽略的。暂时不支持返回台湾省的详细地址信息。
  • 需要对请求参数不准确,进行异常处理
            CRMgeoDto *dto = [CRMgeoDto mj_objectWithKeyValues:responseObject];
            
            if(dto.status.integerValue == 1){
                // 获取经纬度 ,如果失败,提示【获取经纬度失败,请输入准确的经营地址!】
                
                
                
                
                
                
                void (^noLocationdataBlock)(void) = ^void(void) {
                    
                    [SVProgressHUD showInfoWithStatus:@"获取经纬度失败,请输入准确的经营地址!"];
                     

                };
                
//                responseObject:  {
//                    status = 1;
//                    info = OK;
//                    infocode = 10000;
//                    count = 0;
//                    geocodes = (
//                );
                if(dto.geocodes.count<=0){
                    
                    noLocationdataBlock();
                    return ;
                }
                
                CRMgeocodesDto *geocodesDto = dto.geocodes.firstObject;
                
                if([NSStringQCTtoll isBlankString:geocodesDto.location]){
                    noLocationdataBlock();

                    return ;

                    
                }

                NSArray *array = [responseObject[@"geocodes"][0][@"location"] componentsSeparatedByString:@","];
                
                if(array.count<=1){
                    noLocationdataBlock();

                    return;
                }

1.4接口返回的格式

  • 返回的dto模型定义
  • location
            location = "114.468664,38.037057";

2020-04-10 11:43:29.914038+0800 Housekeeper[943:136269] responseObject:  {
    count = 1;
    geocodes =     (
                {
            adcode = 350503;
            building =             {
                name =                 (
                );
                type =                 (
                );
            };
            city = "\U6cc9\U5dde\U5e02";
            citycode = 0595;
            country = "\U4e2d\U56fd";
            district = "\U4e30\U6cfd\U533a";
            "formatted_address" = "\U798f\U5efa\U7701\U6cc9\U5dde\U5e02\U4e30\U6cfd\U533a\U5bcc\U5927\U53a6";
            level = "\U5174\U8da3\U70b9";
            location = "118.620285,24.908597";
            neighborhood =             {
                name =                 (
                );
                type =                 (
                );
            };
            number =             (
            );
            province = "\U798f\U5efa\U7701";
            street =             (
            );
            township =             (
            );
        }
    );
    info = OK;
    infocode = 10000;
    status = 1;
}

1.5 通过逆地理编码进行判断是否在大陆

判断目标经纬度是否在大陆 :https://kunnan.blog.csdn.net/article/details/119685526

通过经纬度进行判断。利用高德SDK进行判断。(如果是手动输入位置信息就进行逆地理编码获取经纬度

/**
 处理地理编码
 */
- (void)setupGeocode{

    __weak __typeof__(self) weakSelf = self;

    if (weakSelf.locationView.adressTextView.text.length > 0) {
        [SVProgressHUD showWithStatus:@"定位中.."];
        AFHTTPSessionManager *managers = [AFHTTPSessionManager manager];
        managers.requestSerializer = [AFHTTPRequestSerializer serializer];

        managers.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"text/plain",@"application/json",@"text/javascript",nil];
        
        
        
//        NSString *urlStr = [NSString stringWithFormat:@"https://restapi.amap.com/v3/geocode/geo"];
        NSString *urlStr = k_amap_geocode;
        
        
        NSDictionary *dict = @{@"key" : @"" , @"address" : weakSelf.locationView.adressTextView.text};
        
        
        
        [managers GET:urlStr parameters:dict progress:^(NSProgress * _Nonnull downloadProgress) {
            
            NSLog(@"downloadProgress:  %@",downloadProgress);
            [SVProgressHUD dismiss];
            
            
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            
            NSLog(@"商户进件→商户详情,重新定位,若输入的地址只有国家+市(例如:中国浙江),点击确定后,去请求第三方地理编码信息(高德API)的时候会转换失败,获取不到经纬度信息。 提示:【获取经纬度失败,请输入详细地址!】 responseObject:  %@",responseObject);
            
            //status
//            返回结果状态值
//            返回值为 0 或 1,0 表示请求失败;1 表示请求成功
            
            
            CRMgeoDto *dto = [CRMgeoDto mj_objectWithKeyValues:responseObject];
            
            if(dto.status.integerValue == 1){
                // 获取经纬度 ,如果失败,提示【获取经纬度失败,请输入准确的经营地址!】
                
                
                
                
                
                
                void (^noLocationdataBlock)(void) = ^void(void) {
                    
                    [SVProgressHUD showInfoWithStatus:@"获取经纬度失败,请输入准确的经营地址!"];
                     

                };
                
//                responseObject:  {
//                    status = 1;
//                    info = OK;
//                    infocode = 10000;
//                    count = 0;
//                    geocodes = (
//                );
                if(dto.geocodes.count<=0){
                    
                    noLocationdataBlock();
                    return ;
                }
                
                CRMgeocodesDto *geocodesDto = dto.geocodes.firstObject;
                
                if([NSStringQCTtoll isBlankString:geocodesDto.location]){
                    noLocationdataBlock();

                    return ;

                    
                }

                NSArray *array = [responseObject[@"geocodes"][0][@"location"] componentsSeparatedByString:@","];
                
                if(array.count<=1){
                    noLocationdataBlock();

                    return;
                }
                
                
                [weakSelf locotionRequestLat:array[1] Lon:array[0] adress:weakSelf.locationView.adressTextView.text];
                

                [weakSelf.locationView.adressTextView resignFirstResponder];
                
                
                weakSelf.locationView.frame = CGRectMake(0, kHeight, kWidth, KWratio(self.locationViewH));
                
                
                
                weakSelf.bacV.hidden = YES;

                
                
            }else{
                
                [SVProgressHUD showInfoWithStatus:@"请输入准确的经营地址!"];

            }
            
//            if ([[NSString stringWithFormat:@"%@",responseObject[@"status"]]isEqualToString:@"1"]) {
                
                
                
                
//            } else {
                
                
                
//            }

        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            [SVProgressHUD showInfoWithStatus:@"网络错误!"];
        }];
    } else {
        [SVProgressHUD showInfoWithStatus:@"请输入经营地址"];
    }
    
    
}


II 腾讯位置服务:文字地址到经纬度的转换能力(webService)

https://lbs.qq.com/service/webService/webServiceGuide/webServiceGeocoder

API: https://apis.map.qq.com/ws/geocoder/v1/?address=

2.1 key的配置

问题:没有启用WebserviceAPI"

"message" : "此key未开启WebserviceAPI功能,您可登录lbs.qq.com,进入控制台key管理界面,找到此key并设置启用WebserviceAPI"

解决方式:

2.2 请求API

/**
 处理地理编码:通过逆地理编码进行判断是否在大陆
 //status  状态码,0为正常,其它为异常,
 */
- (void)setupGeocode:(NSString*)addressText block:(void (^)(CRMGeocoderDto* geocoder))block
{
    
    
    NSString *urlStr = k_amap_geocode_Tencent;
    
    
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    
    
    [params setValue:self.locationManager.apiKey forKey:@"key"];
    [params setValue:addressText forKey:@"address"];
    
    
    
    
    
    [QCTNetworkHelper GETAPI:urlStr parameters:params success:^(NSDictionary* responseObj) {
        
        void (^noLocationdataBlock)(void) = ^void(void) {
            
            [SVProgressHUD showInfoWithStatus:@"获取经纬度失败,请输入准确的经营地址!"];
            
            
        };

        if(![responseObj.allKeys containsObject:@"result"]){
            noLocationdataBlock();
            return ;

        }
        NSDictionary *result = responseObj[@"result"];
        
        
        CRMGeocoderDto *dto = [CRMGeocoderDto mj_objectWithKeyValues:result];
        
        
        if(block){
            block(dto);
            
        }
        
        
        
    } failure:nil bizFailure:nil isShowLoadingDataGif:YES];
    
    
    
    
    
}


2.3 返回数据

{
  "status" : 0,
  "message" : "query ok",
  "result" : {
    "location" : {
      "lng" : 117.15011,
      "lat" : 39.138150000000003
    },
    "address_components" : {
      "district" : "南开区",
      "street_number" : "",
      "province" : "天津市",
      "city" : "天津市",
      "street" : ""
    },
    "similarity" : 0.80000000000000004,
    "title" : "南开区",
    "deviation" : 1000,
    "ad_info" : {
      "adcode" : "120104"
    },
    "level" : 2,
    "reliability" : 1
  }
}

see also

模糊定位适配: https://blog.csdn.net/z929118967/article/details/122086592

用户在高德地图官网申请Web服务API类型Key:https://lbs.amap.com/dev/

开发 > Web服务 API > 开发指南 > API文档 > 地理/逆地理编码 :https://lbs.amap.com/api/webservice/guide/api/georegeo/