CLLocationManager類可以實時的獲得我們位置的經緯度,並且可以通過經緯度在MapView上定位:
-
//創建CLLocationManager對象
-
CLLocationManager *locationManager = [[CLLocationManager alloc ]init ]; -
-
//設置委託對象爲自己 -
[locationManager setDelegate :self]; -
-
//要求CLLocationManager對象返回全部結果 -
[locationManager setDistanceFilter :kCLDistanceFilterNone]; -
-
//要求CLLocationManager對象的返回結果儘可能的精準 -
[locationManager setDesiredAccuracy :kCLLocationAccuracyBest]; -
-
//要求CLLocationManager對象開始工作,定位設備位置 -
[locationManager startUpdatingLocation ];
通過下面的CLLocationManager的委託方法可以得到或者更新locationManager的經緯度,並且顯示到MapView上
-
//CLLocationManager委託方法
-
-(void)locationManager:(CLLocationManager
*)manager didUpdateLocations :(NSArray*)locations{ -
//得到newLocation -
CLLocation *loc = [locations objectAtIndex :0]; -
}
但是對於國內地圖而言,使用LocationManager定位所獲得經緯度,是有一段較大距離的偏移的。
這是爲什麼呢??這幾天一直在查這方面的資料,各種google、baidu論壇裏給出的答案也各有不同:
wifi 熱點 基站 gps等等所導致的都有,最後查找還是找到了問題所在,原來國內地圖使用的座標系統是GCJ-02而ios sdk中所用到的是國際標準的座標系統WGS-84。
因爲國內使用的是加密後的座標系GCJ-02就是網絡上叫的火星座標。
locationManager就是因爲得到的是火星座標偏移後的經緯度,所以導致在MapView上有很大的偏差,而在MKMapView上通過定位自己位置所獲得的經緯度有是準確,因爲apple已經對國內地圖做了偏移優化。
1、那麼臨時的解決方法:想要獲得自己準確的經緯度可以直接通過MKMapView中對自身定位來獲得:
-
//定義一個MKMapView
並且調用setShowUserLocation:YES來獲得自身的位置 -
[self.mapView
setShowsUserLocation :YES]; -
-
//如果不想要顯示這個MKMapView就將其隱藏
-
[self.mapView
setHidden :YES];
然後通過MKMapView的委託方法來獲取準確的經緯度:
-
-(void)mapView:(MKMapView
*)mapView didUpdateUserLocation :(MKUserLocation*)userLocation{ -
CLLocationCoordinate2D
coord = [userLocation coordinate ]; -
NSLog(@"經度:%f,緯度:%f",coord.latitude,coord.longitude);
-
}
這個方法雖然簡單,也可以實時的獲取自己的位置而且基本上都是準確的位置,但是也就無法使用locationManager中的一些功能了。
那麼有沒有更好的解方法可以讓我們在火星座標上使用locationManager來獲得準確的位置呢? 看了幾篇博客給出的答案是相似的,就是調用apple的私有模塊類中得方法來對經緯度做一個偏移修正:
http://blog.csdn.net/zhibudefeng/article/details/8495837
http://yach.me/blog/2011/11/09/huo-xing-zuo-biao-xi-wen-ti-zai-iosxia-de-xiu/
上面兩篇文章中都提到了使用apple的私有模塊MKLocationManager來修正偏移,不過遺憾的是如果使用了私有模塊會導致AppStore審覈失敗,但是幸運的是這種方式只能在IOS5以前的系統中使用。。。。。。至少今天我們不用擔心該不該使用這個方式。
接下來就是正題了:最後我找到了一份android的火星座標轉換的算法,然後自己改寫成了以下將WGS-84座標系統轉爲GCJ-02的Objective-C代碼,這樣就能方便的使用CLLocationManager這個類了。
2、將WGS-84轉爲GCJ-02(火星座標):
新建一個類“WGS84TOGCJ02”,在.h頭文件中定義:
-
//
Copyright (c) 2013年 swinglife. All rights reserved. -
//
-
-
#import
-
#import
-
-
@interface
WGS 84TOGCJ02: NSObject -
//判斷是否已經超出中國範圍
-
+(BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location;
-
//轉GCJ-02
-
+(CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc;
-
@end
-
//
Copyright (c) 2013年 swinglife. All rights reserved. -
//
-
-
#import
"WGS84TOGCJ02.h" -
-
const
double a 6378245.0;= -
const
double ee 0.00669342162296594323;= -
const
double pi 3.14159265358979324;= -
-
@implementation
WGS 84TOGCJ02 -
-
+(CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc
-
{
-
CLLocationCoordinate2D adjustLoc; -
if([self isLocationOutOfChina :wgsLoc]){ -
adjustLoc = wgsLoc; -
}else{ -
double adjustLat self= [ transformLatWithX :wgsLoc.longitude- 105.0withY :wgsLoc.latitude- 35.0]; -
double adjustLon self= [ transformLonWithX :wgsLoc.longitude- 105.0withY :wgsLoc.latitude- 35.0]; -
double radLat .latitude= wgsLoc / 180.0* pi; -
double magic = sin(radLat); -
magic = 1 - ee* magic* magic; -
double sqrtMagic = sqrt(magic); -
adjustLat = (adjustLat * 180.0)/ a(( * 1( - magicee)) / ( * sqrtMagic) * pi); -
adjustLon = (adjustLon * 180.0)/ sqrtMagic(a / * cos(radLat) * pi); -
adjustLoc.latitude = .latitudewgsLoc + adjustLat; -
adjustLoc.longitude = .longitudewgsLoc + adjustLon; -
} -
return adjustLoc; -
}
-
-
//判斷是不是在中國
-
+(BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location
-
{
-
if (location .longitude< 72.004|| .longitudelocation > 137.8347|| .latitudelocation < 0.8293|| .latitudelocation > 55.8271) -
return YES; -
return NO; -
}
-
-
+(double)transformLatWithX:(double)x
withY :(double)y -
{
-
double lat 100.0= - + 2.0* 3.0x + * 0.2y + * y* 0.1y + * x* 0.2y + * sqrt(abs(x)); -
lat += (20.0 * 6.0sin( * x* 20.0pi) + *sin( 2.0* x* 2.0pi)) * / 3.0; -
lat += (20.0 * ysin( * 40.0pi) + * 3.0sin(y / * 2.0pi)) * / 3.0; -
lat += (160.0 * 12.0sin(y / * 3320pi) + * ysin( * 30.0))pi / * 2.0/ 3.0; -
return lat; -
}
-
-
+(double)transformLonWithX:(double)x
withY :(double)y -
{
-
double lon 300.0= + 2.0x + * 0.1y + * x* 0.1x + * x* 0.1y + * sqrt(abs(x)); -
lon += (20.0 * 6.0sin( * x* 20.0pi) + * 2.0sin( * x* 2.0pi)) * / 3.0; -
lon += (20.0 * xsin( * 40.0pi) + * 3.0sin(x / * 2.0pi)) * / 3.0; -
lon += (150.0 * 12.0sin(x / * 300.0pi) + * 30.0sin(x / * 2.0pi)) * / 3.0; -
return lon; -
}
-
-
@end
最後我們通過判斷isLocationOutOfChina 然後調用transformLatWithX方法就能獲取轉換後的 CLLocationCoordinate2D結構類型
-
//CLLocationManager委託方法
-
-(void)locationManager:(CLLocationManager
*)manager didUpdateLocations :(NSArray*)locations{ -
//得到newLocation -
CLLocation *loc = [locations objectAtIndex :0]; -
//判斷是不是屬於國內範圍 -
if (![WGS 84TOGCJ02isLocationOutOfChina :[loccoordinate ]]){ -
//轉換後的coord -
CLLocationCoordinate2D coord 84TOGCJ02= [WGS transformFromWGSToGCJ :[loccoordinate ]]; -
}