一个用来定位当前城市的单例
2016-03-08 13:59
295 查看
整理了一个获取定位当前城市的单例类
ZWMapHelper.h
ZWMapHelper.m
注意:
如果要求在后台也可以定位,// [self.locationManager requestAlwaysAuthorization];//?在后台也可定位 把这行代码放开,并需在info.plist中配置如下:
调用方法:
ZWMapHelper.h
#import <Foundation/Foundation.h> #import <CoreLocation/CoreLocation.h> #import <MapKit/MapKit.h> //定位成功回调 typedef void(^ReturnCurrentCity)(NSString *currentcity); @interface ZWMapHelper : NSObject /// 单例实例 + (ZWMapHelper *) sharedInstance; /// 开始定位并获得位置相关信息 - (void)startLocationAndGetPlaceInfo; /// 地球坐标系(真实GPS坐标)转火星坐标(高德坐标) - (CLLocationCoordinate2D)wgs84ToGcj02:(CLLocationCoordinate2D)wgs84Coor; /// 火星坐标转地球坐标系 - (CLLocationCoordinate2D)gcj02ToWgs84:(CLLocationCoordinate2D)gcj02Coor; /// 坐标是否在中国内 - (BOOL)isInChina:(double)lat lon:(double)lon; @property(nonatomic,copy)ReturnCurrentCity returnBlock; @end
ZWMapHelper.m
#import "ZWMapHelper.h" static ZWMapHelper *_sharedInstance = nil; @interface ZWMapHelper ()<CLLocationManagerDelegate> { BOOL isCity;//判断是否请求到当前城市 } @property (strong, nonatomic) CLLocationManager *locationManager; @property (strong, nonatomic) CLPlacemark *currPlacemark; @property(strong,nonatomic)NSTimer *timer; @end @implementation ZWMapHelper #pragma mark - Class life cycle method + (ZWMapHelper *) sharedInstance { @synchronized(self) { if (_sharedInstance == nil) { _sharedInstance = [[super allocWithZone:NULL] init]; } } return _sharedInstance; } + (id)allocWithZone:(NSZone *)zone { @synchronized(self) { if(_sharedInstance == nil) { _sharedInstance = [super allocWithZone:zone]; return _sharedInstance; } } return nil; } - (id)init { if ((self=[super init])) { //开始定位并获得位置相关信息(如国家等) // [self startLocationAndGetPlaceInfo]; isCity=NO; } return self; } /// 开始定位并获得位置相关信息(如国家等) - (void)startLocationAndGetPlaceInfo { if (self.currPlacemark) return; //如果已取得位置信息则退出 if (!self.locationManager) { // 1. 实例化定位管理器 self.locationManager = [[CLLocationManager alloc] init]; // 2. 设置代理 self.locationManager.delegate = self; // 3. 定位精度 [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest]; // 4.请求用户权限:分为:?只在前台开启定位?在后台也可定位, //注意:建议只请求?和?中的一个,如果两个权限都需要,只请求?即可, //??这样的顺序,将导致bug:第一次启动程序后,系统将只请求?的权限,?的权限系统不会请求,只会在下一次启动应用时请求? self.locationManager.distanceFilter = kCLDistanceFilterNone; //1.0f; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) { [_locationManager requestWhenInUseAuthorization];//?只在前台开启定位 //需在info.plist中配置 // [self.locationManager requestAlwaysAuthorization];//?在后台也可定位 } // 5.iOS9新特性:将允许出现这种场景:同一app中多个location manager:一些只能在前台定位,另一些可在后台定位(并可随时禁止其后台定位)。 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) { self.locationManager.allowsBackgroundLocationUpdates = YES; } self.locationManager.pausesLocationUpdatesAutomatically = NO; //NO表示一直请求定位服务 // 6. 更新用户位置 [self.locationManager startUpdatingLocation]; } //开始定位 [self.locationManager startUpdatingLocation]; } //响应当前位置的更新,在这里记录最新的当前位置 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *newLocation = [locations lastObject]; // //只定位一次 [manager stopUpdatingLocation]; //地球坐标转到火星坐标才能查询出真实地址 CLLocationCoordinate2D gcg02Coord = [self wgs84ToGcj02:newLocation.coordinate]; if (gcg02Coord.latitude>=0 && gcg02Coord.longitude>=0) { [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%f",gcg02Coord.longitude] forKey:@"longitude"]; [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%f",gcg02Coord.latitude] forKey:@"latitude"]; [[NSUserDefaults standardUserDefaults] synchronize]; } CLLocation *convertedLoc = [[CLLocation alloc] initWithLatitude:gcg02Coord.latitude longitude:gcg02Coord.longitude]; CLGeocoder *geocoder = [[CLGeocoder alloc] init]; [geocoder reverseGeocodeLocation:convertedLoc completionHandler:^(NSArray *placemarks, NSError *error) { if ([placemarks count] > 0 && error == nil) { CLPlacemark *placemark = [placemarks objectAtIndex:0]; NSArray *languages = [NSLocale preferredLanguages]; NSString *currentLanguage = [languages objectAtIndex:0]; NSString *language; //判断模拟器的语言环境 if (currentLanguage&&![currentLanguage isKindOfClass:[NSNull class]]) { if (currentLanguage.length>=@"zh-Hans".length) { language=[currentLanguage substringToIndex:@"zh-Hans".length]; } } NSString *currentCity; if (language) { if ([language isEqualToString:@"zh-Hans"]) { //因为四大直辖市的城市信息无法通过locality获得,只能通过获取省份的方法来获得(如果city为空,则可知为直辖市 if (placemark.locality) { currentCity = [placemark.locality substringToIndex:placemark.locality.length - 1]; } else { currentCity = [placemark.administrativeArea substringToIndex:placemark.administrativeArea.length - 1]; } } else { //本地是英文时 if (placemark.locality) { currentCity = placemark.locality; } else { currentCity = placemark.administrativeArea; } } if (currentCity) { if (self.returnBlock&&isCity!=YES) { isCity=YES; self.returnBlock(currentCity); } } } } }]; } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { //只定位一次 [manager startUpdatingLocation]; } #pragma mark - 地球坐标(原始GPS坐标)和火星坐标(高德/Google中国)互转 const double g_pi = 3.14159265358979324; const double g_a = 6378245.0; const double g_ee = 0.00669342162296594323; - (CLLocationCoordinate2D)wgs84ToGcj02:(CLLocationCoordinate2D)wgs84Coor { CLLocationCoordinate2D gcj02Coor; if (outOfChina(wgs84Coor.latitude, wgs84Coor.longitude)) { gcj02Coor = wgs84Coor; return gcj02Coor; } double dLat = transformLat(wgs84Coor.longitude-105.0, wgs84Coor.latitude-35.0); double dLon = transformLon(wgs84Coor.longitude-105.0, wgs84Coor.latitude-35.0); double radLat = wgs84Coor.latitude/180.0*g_pi; double magic = sin(radLat); magic = 1-g_ee*magic*magic; double sqrtMagic = sqrt(magic); dLat = (dLat * 180.0) / ((g_a * (1 - g_ee)) / (magic * sqrtMagic) * g_pi); dLon = (dLon * 180.0) / (g_a / sqrtMagic * cos(radLat) * g_pi); gcj02Coor = CLLocationCoordinate2DMake(wgs84Coor.latitude+dLat, wgs84Coor.longitude+dLon); return gcj02Coor; } #pragma mark-火星坐标转地球坐标 - (CLLocationCoordinate2D)gcj02ToWgs84:(CLLocationCoordinate2D)gcj02Coor { double lon = gcj02Coor.longitude; double lat = gcj02Coor.latitude; CLLocationCoordinate2D coor = [self wgs84ToGcj02:gcj02Coor]; double lontitude = lon - (coor.longitude - lon); double latitude = lat - (coor.latitude - lat); return CLLocationCoordinate2DMake(latitude, lontitude); } #pragma mark-判断是中国还是外国 - (BOOL)isInChina:(double)lat lon:(double)lon { return outOfChina(lat, lon) ? NO : YES ; } #pragma mark-判断是中国还是外国 bool outOfChina(double lat, double lon) { //缓存中未拿到国家信息 if ([ZWMapHelper sharedInstance].currPlacemark) { NSString *countryCode = [ZWMapHelper sharedInstance].currPlacemark.ISOcountryCode; if (!countryCode || countryCode.length < 1) return false; //默认认为在中国 // if ([countryCode isEqualToString:@"CN"] ) { return false; } } if (lon < 72.004 || lon > 137.8347) return true; if (lat < 0.8293 || lat > 55.8271) return true; return false; } #pragma mark-转换经度 double transformLat(double x, double y) { double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(abs(x)); ret += (20.0 * sin(6.0 * x * g_pi) + 20.0 * sin(2.0 * x * g_pi)) * 2.0 / 3.0; ret += (20.0 * sin(y * g_pi) + 40.0 * sin(y / 3.0 * g_pi)) * 2.0 / 3.0; ret += (160.0 * sin(y / 12.0 * g_pi) + 320 * sin(y * g_pi / 30.0)) * 2.0 / 3.0; return ret; } #pragma mark-转换纬度 double transformLon(double x, double y) { double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(abs(x)); ret += (20.0 * sin(6.0 * x * g_pi) + 20.0 * sin(2.0 * x * g_pi)) * 2.0 / 3.0; ret += (20.0 * sin(x * g_pi) + 40.0 * sin(x / 3.0 * g_pi)) * 2.0 / 3.0; ret += (150.0 * sin(x / 12.0 * g_pi) + 300.0 * sin(x / 30.0 * g_pi)) * 2.0 / 3.0; return ret; }
注意:
如果要求在后台也可以定位,// [self.locationManager requestAlwaysAuthorization];//?在后台也可定位 把这行代码放开,并需在info.plist中配置如下:
调用方法:
ZWMapHelper *helper= [ZWMapHelper sharedInstance]; [helper startLocationAndGetPlaceInfo]; helper.returnBlock=^(NSString * currentcity){ NSLog(@"%@====>",currentcity); };
相关文章推荐
- SAP接口编程-RFC系列13 : Table Parameter作为输入参数
- pascal产生的hpp文件报:E2040 Declaration terminated incorrectly
- typedef和#define的作用范围
- VR 终极选购指南:入门、进阶与高端
- jvm
- 生还是死?Android 进程优先级详解
- iOS 上传图片到服务器 最简单的实现方式
- 在升级过内核的机器上安装docker遇到的一个错误
- iOS 在viewController中改变状态栏颜色
- HTML的块级元素与内联元素
- hibernate 通过API访问数据库
- codeforces 598D - Igor In the Museum
- 深入理解PHP原理之变量分离/引用
- android Service总结
- spring aop 异常记录
- iOS 最常用的第三方框架
- 如何在非管理员系统下修改hosts文件
- 日本JATE认证
- 关于哈希表
- background-size和background-position用法