//
// YALocationInfo.h
// YATestFramework
//
// Created by MacDev1 on 15/6/25.
// Copyright (c) 2015年 yanan. All rights reserved.
//
/*
* 需要导入 CoreLocation.framework
*/
#import
#import
@class YALocationInfor;
typedef NS_ENUM(NSInteger, LocationResult) {
FAIL = 0,
SUCCESS ,
};
typedef void(^LocBlock)(YALocationInfor *locInforModel, LocationResult locRes, NSError *error);
@interface YALocationInfor : NSObject
/**
* @brief YES 有定位的信息可以使用(可以自行决定是否再次调用 getUserCurrentLocationInfo 定位);NO 还没有进行定位或者定位尚未成功过
*/
@property (assign, nonatomic, readonly) BOOL isHaveLocInfor;
/**
* @brief 用户当前的纬度
*/
@property (assign, nonatomic, readonly) CLLocationDegrees uLatitude;
/**
* @brief 用户当前的经度
*/
@property (assign, nonatomic, readonly) CLLocationDegrees uLongitude;
/**
* @brief 国家
*/
@property (strong, nonatomic, readonly) NSString *uCounty;
/**
* @brief 国家码
*/
@property (strong, nonatomic, readonly) NSString *uCountryCode;
/**
* @brief 省或直辖市
*/
@property (strong, nonatomic, readonly) NSString *uProvince;
/**
* @brief 城市
*/
@property (strong, nonatomic, readonly) NSString *uCity;
/**
* @brief 完整的详细信息
*/
@property (strong, nonatomic, readonly) NSString *uAddress;
/**
* @brief 街道
*/
@property (strong, nonatomic, readonly) NSString *uStreet;
/**
* @brief 区 e.g. 昌平区
*/
@property (strong, nonatomic, readonly) NSString *uSubLocality;
/**
* @brief 门牌号
*/
@property (strong, nonatomic, readonly) NSString *uSubThoroughfare;
/**
* @brief 路名
*/
@property (strong, nonatomic, readonly) NSString *uThoroughfare;
/**
* @brief 地址详情
*/
@property (strong, nonatomic, readonly) NSString *uDetailLocString;
/**
* @brief 单例
*
* @return
*/
+ (YALocationInfor *)shareLocationInforModel;
/**
* @brief 定位(或重新定位)获取用户当前位置信息
*
* @return
*/
- (void)getUserCurrentLocationInfo:(LocBlock)LocationBlock;
/**
* 根据2个经纬度计算距离
*/
+(double) LantitudeLongitudeDist:(double)lon1 other_Lat:(double)lat1 self_Lon:(double)lon2 self_Lat:(double)lat2;
@end
//
// YALocationInfo.m
// YATestFramework
//
// Created by MacDev1 on 15/6/25.
// Copyright (c) 2015年 yanan. All rights reserved.
//
#import "YALocationInfor.h"
@interface YALocationInfor ()
@property (strong, nonatomic) CLLocationManager *mLocationManager;
@property (copy, nonatomic) LocBlock mLocationBlock;
@end
@implementation YALocationInfor
#pragma mark - 单例
static YALocationInfor *single = nil;
+ (YALocationInfor *)shareLocationInforModel {
@synchronized(self) {
if (!single) {
single = [[YALocationInfor alloc]init];
// 调用获取位置信息的方法
[single getUserCurrentLocationInfo:NULL];
}
return single;
}
}
#pragma mark - 开始获取用户当前的位置信息
- (void)getUserCurrentLocationInfo:(LocBlock)LocationBlock {
_mLocationBlock = LocationBlock;
if (!_mLocationManager) {
_mLocationManager = [[CLLocationManager alloc]init];
_mLocationManager.distanceFilter = kCLDistanceFilterNone; // meters
_mLocationManager.delegate = self;
_mLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
if (IS_IOS8_LATER) {
/* 需要在info中新增两个key NSLocationAlwaysUsageDescription 和 NSLocationWhenInUseUsageDescription */
//使用期间
[_mLocationManager requestWhenInUseAuthorization];
//始终
// [self.locationManage requestAlwaysAuthorization]
}
}
if (_mLocationManager)
[_mLocationManager startUpdatingLocation];
}
#pragma mark - 成功获取定位数据后
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation *currentLocation = [locations lastObject];
_uLatitude = currentLocation.coordinate.latitude;
_uLongitude = currentLocation.coordinate.longitude;
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:currentLocation
completionHandler:^(NSArray *array, NSError *error) {
if (array.count > 0) {
CLPlacemark *placemark = [array objectAtIndex:0];
[self locSuccessSet:placemark];
if (_mLocationBlock)
_mLocationBlock(self, SUCCESS, error);
} else if (error == nil && [array count] == 0) {
if (_mLocationBlock)
_mLocationBlock(self, FAIL, error);
} else if (error != nil) {
if (_mLocationBlock)
_mLocationBlock(self, FAIL, error);
}
}];
[_mLocationManager stopUpdatingLocation];
}
#pragma mark - 定位失败时回调
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
if (_mLocationBlock) {
_mLocationBlock(self, FAIL, error);
}
}
#pragma mark - 处理定位成功后,反向地理编码得到的信息
- (void)locSuccessSet:(CLPlacemark *)placemark {
_isHaveLocInfor = YES;
//获取城市
NSString *city = placemark.locality;
if (!city) {
// 四大直辖市的城市信息无法通过locality获得,只能通过获取省份的方法来获得(如果city为空,则可知为直辖市)
city = placemark.administrativeArea;
}
_uCity = city;
_uCounty = [placemark.addressDictionary objectForKey:@"Country"];
_uCountryCode = [placemark.addressDictionary objectForKey:@"CountryCode"];
_uProvince = [placemark.addressDictionary objectForKey:@"State"];
_uAddress = [placemark.addressDictionary objectForKey:@"FormattedAddressLines"];
_uStreet = [placemark.addressDictionary objectForKey:@"Street"];
_uSubLocality = [placemark.addressDictionary objectForKey:@"SubLocality"];
_uSubThoroughfare = [placemark.addressDictionary objectForKey:@"SubThoroughfare"];
_uThoroughfare = [placemark.addressDictionary objectForKey:@"Thoroughfare"];
_uDetailLocString = [[NSString alloc]initWithFormat:@"%@%@%@",_uProvince?_uProvince:@"",_uSubLocality?_uSubLocality:@"",_uStreet?_uStreet:@""];
// FIXLog(@"\n\n\n\nplacemark.addressDictionary = %@\n\n\n\n",placemark.addressDictionary);
}
#pragma mark - iOS8 新增回调方法
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
switch (status) {
case kCLAuthorizationStatusNotDetermined:
if ([_mLocationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[_mLocationManager requestWhenInUseAuthorization];
}
break;
default:
break;
}
}
/**
* 根据2个经纬度计算距离
*/
//+(NSString *) LantitudeLongitudeDist:(double)lon1 other_Lat:(double)lat1 self_Lon:(double)lon2 self_Lat:(double)lat2
//{
//
// CLLocation *orig=[[CLLocation alloc] initWithLatitude:lat2 longitude:lon2] ;
// CLLocation* dist=[[CLLocation alloc] initWithLatitude:lat1 longitude:lon1];
//
// CLLocationDistance kilometers=[orig distanceFromLocation:dist] / 1000;
//
//
// return [NSString stringWithFormat:@"%0.2f",kilometers];
//}
#define PI 3.1415926
+(double) LantitudeLongitudeDist:(double)lon1 other_Lat:(double)lat1 self_Lon:(double)lon2 self_Lat:(double)lat2{
double er = 6378137; // 6378700.0f;
//ave. radius = 6371.315 (someone said more accurate is 6366.707)
//equatorial radius = 6378.388
//nautical mile = 1.15078
double radlat1 = PI*lat1/180.0f;
double radlat2 = PI*lat2/180.0f;
//now long.
double radlong1 = PI*lon1/180.0f;
double radlong2 = PI*lon2/180.0f;
if( radlat1 < 0 ) radlat1 = PI/2 + fabs(radlat1);// south
if( radlat1 > 0 ) radlat1 = PI/2 - fabs(radlat1);// north
if( radlong1 < 0 ) radlong1 = PI*2 - fabs(radlong1);//west
if( radlat2 < 0 ) radlat2 = PI/2 + fabs(radlat2);// south
if( radlat2 > 0 ) radlat2 = PI/2 - fabs(radlat2);// north
if( radlong2 < 0 ) radlong2 = PI*2 - fabs(radlong2);// west
//spherical coordinates x=r*cos(ag)sin(at), y=r*sin(ag)*sin(at), z=r*cos(at)
//zero ag is up so reverse lat
double x1 = er * cos(radlong1) * sin(radlat1);
double y1 = er * sin(radlong1) * sin(radlat1);
double z1 = er * cos(radlat1);
double x2 = er * cos(radlong2) * sin(radlat2);
double y2 = er * sin(radlong2) * sin(radlat2);
double z2 = er * cos(radlat2);
double d = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
//side, side, side, law of cosines and arccos
double theta = acos((er*er+er*er-d*d)/(2*er*er));
double dist = theta*er;
return dist / 1000;
}
@end