一个用来定位当前城市的单例

整理了一个获取定位当前城市的单例类
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);
    };
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值