您的位置:首页 > 其它

定位、地理编码、逆地理编码

2016-05-03 14:21 459 查看

先看效果



代码下载

代码下载请猛戳这里!

再看代码

- (CLLocationManager *)locationManager
{
//是否允许定位
/**
*  [CLLocationManager locationServicesEnabled] 确定用户是否已启用位置服务。
*  [CLLocationManager authorizationStatus] 返回调用应用程序的当前授权状态。
kCLAuthorizationStatusDenied:用户已经明确地拒绝了该应用程序的授权,或者
在设置中禁用位置服务。
kCLAuthorizationStatusNotDetermined:用户尚未对该应用程序作出选择
*/
NSLog(@"%i,%i",[CLLocationManager locationServicesEnabled],[CLLocationManager authorizationStatus]);
if ((![CLLocationManager locationServicesEnabled]) || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
[self showAlertViewControllerWithMessage:@"请到\"设置—隐私—定位服务\"开启本软件的定位服务"];
return nil;
}

if (!_locationManager) {
//创建定位管理者
_locationManager = [[CLLocationManager alloc] init];
//设置管理者代理
_locationManager.delegate = self;
//desiredAccuracy:所需的位置精度。位置服务将尽力实现
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//distanceFilter:指定米的最小更新距离。distanceFilter的值越小,应用程序的耗电量就越大。
_locationManager.distanceFilter = 1000.0f;
//如果是iOS8以上系统
if ([[UIDevice currentDevice].systemVersion floatValue] > 8.0) {
//requestAlwaysAuthorization: 总是允许访问地理信息,需要在plist文件中设置NSLocationAlwaysUsageDescription
//            [_locationManager requestAlwaysAuthorization];
//requestWhenInUseAuthorization: 在使用应用期间允许访问地理信息,需要在plist文件中设置NSLocationWhenInUseUsageDescription
[_locationManager requestWhenInUseAuthorization];
}
}

return _locationManager;
}

#pragma mark - 控制器周期
- (void)dealloc
{
//移除通知
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)viewDidLoad {
[super viewDidLoad];

[self.locTextField becomeFirstResponder];

//distanceFromLocation: 计算两个CLLocation对象的距离
NSLog(@"衡阳到长沙:%f米",[[[CLLocation alloc] initWithLatitude:28.194 longitude:112.982] distanceFromLocation:[[CLLocation alloc] initWithLatitude:29.6 longitude:112.6]]);

//监听键盘通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardChanged:) name:UIKeyboardWillChangeFrameNotification object:nil];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];

[self.locationManager startUpdatingLocation];
}

#pragma mark - 触摸点击方法
- (IBAction)locationAction:(UIButton *)sender {
/**
*  如果是iOS9的系统,定位的代理方法还是不会执行的,因为iOS9引入了新特性App Transport Security (ATS)。
解决方案:首先在Info.plist中添加NSAppTransportSecurity类型Dictionary。
然后在NSAppTransportSecurity下添加NSAllowsArbitraryLoads类型Boolean,值设为YES
*/
[self.locationManager startUpdatingLocation];
}
- (IBAction)geocodingAction:(UIButton *)sender {
if (![self isBlinkStr:self.locTextField.text]) {
[self geoCodingLocationStr:self.locTextField.text];
}
}
- (IBAction)reGeocodingAction:(UIButton *)sender {
[self.view endEditing:YES];

if ((![self isBlinkStr:self.reLatitudeTextField.text] && (![self isBlinkStr:self.reLongitudeTextField.text]))) {
[self reGeoCodingLatitude:[self.reLatitudeTextField.text doubleValue] andLongitude:[self.reLongitudeTextField.text doubleValue]];
}
else
{
[self showAlertViewControllerWithMessage:@"请输入经纬度!"];
}
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
/*
UIKeyboardAnimationCurveUserInfoKey = 7;  // 动画的执行节奏(速度)
UIKeyboardAnimationDurationUserInfoKey = "0.25"; // 键盘弹出\隐藏动画所需要的时间
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";
UIKeyboardFrameChangedByUserInteraction = 0;

// 键盘弹出
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";// 键盘刚出来那一刻的frame
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}"; //  键盘显示完毕后的frame

// 键盘隐藏
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";
*/
- (void)keyBoardChanged:(NSNotification *)sender
{
UIView *view = [self findFirstResponder:self.view];
CGRect keyBF = [sender.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat distance = CGRectGetMaxY(view.frame) - keyBF.origin.y;

//首尾式动画
[UIView beginAnimations:nil context:nil];
//设置动画时间
[UIView setAnimationDuration:[sender.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
//设置动画节奏
[UIView setAnimationCurve:[sender.userInfo[UIKeyboardAnimationDurationUserInfoKey] integerValue]];
//设置动画
if (distance > 0) {
CGFloat spacing = 8;
self.view.transform = CGAffineTransformMakeTranslation(0, -distance - spacing);
}
else
{
self.view.transform = CGAffineTransformIdentity;
}
}

#pragma mark - 自定义方法
/**
*  地理编码
*
*  @param str 地名
*/
- (void)geoCodingLocationStr:(NSString *)str
{
//地理编码
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:str completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (error) {
[self showAlertViewControllerWithMessage:@"您的地址输入有误!"];
}
else
{
//注意取出最前面的地址(准确)
//CLPlacemark:代表一个地理位置的地标数据。
CLPlacemark *placeMark = [placemarks firstObject];
self.latitudeTextField.text = [NSString stringWithFormat:@"%f",placeMark.location.coordinate.latitude];
self.longitudeTextField.text = [NSString stringWithFormat:@"%f",placeMark.location.coordinate.longitude];
self.detailLocTextField.text = placeMark.name;
}
}];
}
/**
*  逆地理编码
*
*  @param latitude  纬度
*  @param longitude 经度
*/
- (void)reGeoCodingLatitude:(CLLocationDegrees)latitude andLongitude:(CLLocationDegrees)longitude
{
//取出CLLocation位置对象
CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
//逆地理编码
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (error) {
[self showAlertViewControllerWithMessage:@"没有找到此经纬度的地理信息!"];
}
else
{
//注意取出最前面的地址(准确)
//CLPlacemark:代表一个地理位置的地标数据。
CLPlacemark *pMark = [placemarks firstObject];
self.reDetailLocTextField.text = pMark.name;
}
}];
}
/**
*  字符串判空
*/
- (BOOL)isBlinkStr:(NSString *)str
{
/**
*  stringByTrimmingCharactersInSet函数过滤字符串中的特殊符号
*/
if (str == nil || str == NULL) {
return YES;
}
else if ([str isKindOfClass:[NSNull class]])
{
return YES;
}
else if ([[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0)//去掉两端的空白字符
{
return YES;
}

return NO;
}
/**
*  显示提示框
*
*  @param message 提示的信息
*/
- (void)showAlertViewControllerWithMessage:(NSString *)message
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
}
/**
*  查找第一响应者
*
*  @param view 从哪个视图上查找
*
*  @return 第一响应者View
*/
- (UIView *)findFirstResponder:(UIView *)view
{
if ([view isFirstResponder]) {
return view;
}
for (UIView *theView in view.subviews) {
UIView *firstView = [self findFirstResponder:theView];
if (firstView) {
return firstView;
}
}

return nil;
}

#pragma mark - <CLLocationManagerDelegate>代理方法
/**
*  只要定位到用户信息就会调用此方法(调用的平率非常高)
*
*  @param manager   定位管理者
*  @param locations  装着CLLocation对象
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
//此处locations存储了持续更新的位置坐标值,取最后一个值为最新位置,如果不想让其持续更新位置,则在此方法中获取到一个值之后让locationManager stopUpdatingLocation
CLLocation *location = [locations lastObject];
//逆地理编码
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (error) {
NSLog(@"此地址错误");
}
else
{
//取出最前面的地址(准确)
CLPlacemark *pMark = [placemarks firstObject];
self.currentLocTextField.text = pMark.name;
NSLog(@"%f,%f,%@,%@,%@",location.coordinate.latitude,location.coordinate.longitude,pMark.name,pMark.locality,pMark.addressDictionary[@"City"]);
}
}];
//停止定位(省电措施:只要不想用定位服务,就马上停止定位服务)
[manager stopUpdatingLocation];
}

#pragma mark - <UITextFieldDelegate>代理方法
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.locTextField && (![self isBlinkStr:self.locTextField.text])) {
[self geoCodingLocationStr:self.locTextField.text];
}
else if ((textField == self.reLatitudeTextField || textField == self.reLongitudeTextField) && (![self isBlinkStr:self.latitudeTextField.text]) && (![self isBlinkStr:self.longitudeTextField.text]))
{
[self reGeoCodingLatitude:[self.reLatitudeTextField.text doubleValue] andLongitude:[self.reLongitudeTextField.text doubleValue]];
}
[textField resignFirstResponder];

return YES;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息