標籤:ios 經緯度
進行中的項目中有這樣的需求:定位獲得當前經緯度,再用百度Place API使用經緯度查詢周邊資訊。這裡不需要顯示地圖,只需要定位。看似思路很順暢,做起來卻不容易。
iPhone的GPS定位(CLLocationManager)獲得的經緯座標是基於WGS-84座標系(世界標準),Google地圖使用的是GCJ-02座標系(中國特色的火星座標系),這就是為什麼獲得的經緯座標在google地圖上會發生位移。我項目需求是使用百度Place API,百度的經緯座標在GCJ-02的基礎上再做了次加密,就是DB-09座標系。就想使用百度地圖的IOS SDK,裡面的座標系統都是一致的而不用轉換,由於不想讓項目太大,所以沒有用百度的sdk,所以另闢蹊徑了。
在網上搜尋一番,有現成百度的介面轉換座標,經實驗 從WGS-84到GCJ-02,再到DB-09,經兩次轉換後,順利獲得當前正確地理位置資訊和周邊資訊,當然這些資訊是來自百度的。
ZYLocationManager.h
#import <Foundation/Foundation.h>#import <CoreLocation/CoreLocation.h>#import "Singleton.h"typedef void(^locationBlock)(CLLocationCoordinate2D coor);typedef void(^addressBlock)(NSString *address);@interface ZYLocationManager : NSObjectsingleton_interface(ZYLocationManager)/** * 擷取糾偏後的經緯度(百度地圖經緯度) */- (void) getLocationCoordinate:(locationBlock) locaiontBlock;/** * 擷取糾偏後的經緯度(百度地圖經緯度)和地址 */- (void) getLocationCoordinate:(locationBlock) locaiontBlock address:(addressBlock) addressBlock;@end
ZYLocationManager.m
#import "ZYLocationManager.h"#import "AFNetworking.h"#define IOS_Version [[UIDevice currentDevice].systemVersion floatValue]@interface ZYLocationManager ()<CLLocationManagerDelegate>{// 儲存block locationBlock _locationBlock; addressBlock _addressBlock;}@property (nonatomic, strong) CLLocationManager *lm;@end@implementation ZYLocationManagersingleton_implementation(ZYLocationManager)/** * 懶載入 */- (CLLocationManager *)lm{ if (!_lm) { _lm = [[CLLocationManager alloc] init]; _lm.delegate = self; // 定位精準度 _lm.desiredAccuracy = kCLLocationAccuracyBest; // 重新置放的距離 _lm.distanceFilter = 1000.0f; } return _lm;}/** * 類第一次使用的時候被調用 */+ (void)initialize{ ZYLocationManager *manager = [self sharedZYLocationManager]; // ios8後需要向使用者請求許可權 if (IOS_Version >= 8.0) { [manager.lm requestWhenInUseAuthorization]; [manager.lm requestAlwaysAuthorization]; } // 開始定位 [manager.lm startUpdatingLocation];}#pragma mark - CLLocationManager擷取經緯度的代理方法- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ CLLocation *location = [locations lastObject]; CLLocationCoordinate2D coor = location.coordinate;// NSLog(@"緯度:%.6f 經度%.6f", coor.latitude, coor.longitude); NSString *x1 = [NSString stringWithFormat:@"%f", coor.longitude]; NSString *y1 = [NSString stringWithFormat:@"%f", coor.latitude]; // http://api.map.baidu.com/ag/coord/convert?from=0&to=2&x=113.377346&y=23.132648 __block NSDictionary *dict1 = @{@"from":@"0", @"to":@"2", @"x":x1, @"y":y1 }; AFHTTPRequestOperationManager *roManager = [AFHTTPRequestOperationManager manager]; // 1、ios系統經緯度(國際標準)轉Google經緯度 [roManager GET:@"http://api.map.baidu.com/ag/coord/convert" parameters:dict1 success:^(AFHTTPRequestOperation *operation, id responseObject) { __block NSString *resultX = [self base64Decode:responseObject[@"x"]]; __block NSString *resultY = [self base64Decode:responseObject[@"y"]]; dict1 = @{@"from":@"2", @"to":@"4", @"x":resultX, @"y":resultY }; // 2、Google經緯度轉百度經緯度 [roManager GET:@"http://api.map.baidu.com/ag/coord/convert" parameters:dict1 success:^(AFHTTPRequestOperation *operation, id responseObject) { resultX = [self base64Decode:responseObject[@"x"]]; resultY = [self base64Decode:responseObject[@"y"]]; CLLocationCoordinate2D resultCoor = CLLocationCoordinate2DMake([resultY floatValue], [resultX floatValue]); // 給block賦值 if (_locationBlock) { _locationBlock(resultCoor); } [self getAddressWithCoordinate:resultCoor]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@", error); }]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@", error); }]; // 停止定位 [self.lm stopUpdatingLocation];}- (void)getLocationCoordinate:(locationBlock)locaiontBlock{ _locationBlock = locaiontBlock;}- (void)getLocationCoordinate:(locationBlock)locaiontBlock address:(addressBlock)addressBlock{ _locationBlock = locaiontBlock; _addressBlock = addressBlock;}#pragma mark - base64解密- (NSString *)base64Decode:(NSString *)str{ // 1、加密字串轉位元據 NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters]; // 2、位元據轉字串 return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];}#pragma mark - 經緯度轉地址- (void)getAddressWithCoordinate:(CLLocationCoordinate2D)coor{ if (coor.latitude == 0 || coor.longitude == 0) return; CLLocation *loca = [[CLLocation alloc] initWithLatitude:coor.latitude longitude:coor.longitude]; CLGeocoder *geocoder = [[CLGeocoder alloc] init]; [geocoder reverseGeocodeLocation:loca completionHandler:^(NSArray *placemarks, NSError *error) { if (placemarks.count == 0 || error) return; CLPlacemark *pm = [placemarks lastObject]; if (_addressBlock) { _addressBlock(pm.thoroughfare); } }];}@end
IOS8後,請求定位需要請求許可權,代碼ZYLocationManager.m已經寫好了,不過還需要在info.plist中,添加兩個屬性NSLocationAlwaysUsageDescription和NSLocationWhenInUseUsageDescription,屬性值即是你需要提示給使用者的資訊,如所示:
將ZYLocationManager.h和ZYLocationManager.m拖入項目中,即可直接調用ZYLocationManager.h定義的兩個方法,擷取到百度經緯度和地址。
ios系統經緯度轉百度經緯度及經緯度轉地址