本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正。


本文相关目录:

================== 所属文集:【iOS】07 设备工具 ==================

7.4 定位服务->1.0 简介

7.4 定位服务->2.1.1 定位 - 官方框架CoreLocation: 请求用户授权

7.4 定位服务->2.1.2 定位 - 官方框架CoreLocation: CLLocationManager位置管理器

7.4 定位服务->2.1.3.1 定位 - 官方框架CoreLocation 功能1:地理定位

7.4 定位服务->2.1.3.2 定位 - 官方框架CoreLocation 功能2:地理编码和反地理编码

7.4 定位服务->2.1.3.3 定位 - 官方框架CoreLocation 功能3:区域监听

7.4 定位服务->2.1.4 定位 - 官方框架CoreLocation 案例:指南针效果

7.4 定位服务->2.2 定位 - locationManager框架

7.4 定位服务->3.1 地图框架MapKit 功能1:地图展示

7.4 定位服务->3.2 地图框架MapKit 功能2:路线规划(导航)

7.4 定位服务->3.3 地图框架MapKit 功能3:3D视图

7.4 定位服务->3.4 地图框架MapKit 功能4:地图截图

7.4 定位服务->3.5 地图框架MapKit 功能5:POI检索

================== 所属文集:【iOS】07 设备工具 ==================


定位目录:

官方框架CoreLocation目录:

定位的功能实现:

本文目录:


1.0 概念解释


2.0 相关方法

下面介绍下CLPlacemark对象相关的知识:


3.0 实现步骤

代码5:

编译环境:Xcode 8.0

模拟器版本:iOS 10

Swift版本:3.0

【OC 语言】

#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <AddressBook/AddressBook.h> @interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextView *addressTextView;// 地址
@property (weak, nonatomic) IBOutlet UITextField *latitudeTextField;// 纬度
@property (weak, nonatomic) IBOutlet UITextField *longitudeUITextField;// 经度
@property(nonatomic, strong) CLGeocoder *geoCoder;   // 用作地理编码、反地理编码的工具类
@end @implementation ViewController #pragma mark - 懒加载
- (CLGeocoder *)geoCoder {
    if (!_geoCoder) {
        _geoCoder = [[CLGeocoder alloc] init];
    }
    return _geoCoder;
} #pragma mark - 地理编码(地址->经纬度)
- (IBAction)geoCode:(UIButton *)sender {
    
    // 判断输入地址的 text 是否为空
    if ([self.addressTextView.text length] == 0) {
        return;
    }
    
#pragma mark - 地理编码方案1:根据地址字符串解析,进行地理编码(返回结果可能有多个,因为一个地点有重名)
    [self.geoCoder geocodeAddressString:self.addressTextView.text
                      completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
                          
                          // 防错处理
                          if (error || placemarks.count == 0) {
                              NSLog(@"地理编码错误:%@", error);
                              return;
                          }
                          
                          // 罗列出所有搜索到的地址名称
                          for (CLPlacemark *placemark in placemarks) {
                              NSLog(@"所有搜索到的地址名称:%@",placemark.name);
                          }
                          
                          // 一个placemark对应一个地理坐标,包含一个地方的信息(因为可能有多种结果,所有是一个数组,因此要给用户一个列表去选择)
                          CLPlacemark *placemark = [placemarks firstObject]; // 包含区,街道等信息的地标对象
                          NSLog(@"搜索到的第一个城市名:%@,搜索到的第一个地址名称:%@", placemark.locality, placemark.name);
                          
                          // 显示搜索到的第一个地址名称,到 addressTextView 中
                          self.addressTextView.text = [NSString stringWithFormat:@"%@", placemark.name];
                          // 显示纬度(拼接字符串),到 latitudeTextField
                          self.latitudeTextField.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
                          // 显示经度(拼接字符串),到 longitudeUITextField
                          self.longitudeUITextField.text =[NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
                      }];
    
    
#pragma mark - 地理编码方案2:在区域内根据地址字符串解析,进行地理编码(更加精确)
    [self.geoCoder geocodeAddressString:self.addressTextView.text
                               inRegion:nil
                      completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
                          
                          // 防错处理
                          if (error || placemarks.count == 0) {
                              NSLog(@"地理编码错误:%@", error);
                              return;
                          }
                          
                          // 罗列出所有搜索到的地址名称
                          for (CLPlacemark *placemark in placemarks) {
                              NSLog(@"所有搜索到的地址名称:%@",placemark.name);
                          }
                          
                          // 一个placemark对应一个地理坐标,包含一个地方的信息(因为可能有多种结果,所有是一个数组,因此要给用户一个列表去选择)
                          CLPlacemark *placemark = [placemarks firstObject]; // 包含区,街道等信息的地标对象
                          NSLog(@"搜索到的第一个城市名:%@,搜索到的第一个地址名称:%@", placemark.locality, placemark.name);
                          
                          // 显示搜索到的第一个地址名称,到 addressTextView 中
                          self.addressTextView.text = [NSString stringWithFormat:@"%@", placemark.name];
                          // 显示纬度(拼接字符串),到 latitudeTextField
                          self.latitudeTextField.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
                          // 显示经度(拼接字符串),到 longitudeUITextField
                          self.longitudeUITextField.text =[NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
                      }];
    
#pragma mark - 地理编码方案3:根据地址信息字典解析,进行地理编码(不推荐)
    NSDictionary *addressDic = @{
                                 (__bridge NSString *)kABPersonAddressStreetKey:@"杭州",(__bridge NSString *)kABPersonAddressStreetKey:@"上海"
                                 };
    
    [self.geoCoder geocodeAddressDictionary:addressDic
                          completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
                              // code
                          }];
} #pragma mark - 清空
- (IBAction)clearButton:(UIButton *)sender {
    self.addressTextView.text = NULL;
    self.latitudeTextField.text = NULL;
    self.longitudeUITextField.text = NULL;
} #pragma mark - 反地理编码:根据给定的经纬度,获得具体的位置信息
- (IBAction)reverseGeoCode:(UIButton *)sender {
    
    // 过滤空数据
    if ([self.latitudeTextField.text length] == 0 ||
        [self.longitudeUITextField.text length] == 0) {
        return;
    }
    
    // 创建CLLocation对象
    double latitude = [self.latitudeTextField.text doubleValue];
    double longitude = [self.longitudeUITextField.text doubleValue];
    CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
    
    // 根据CLLocation对象进行反地理编码
    [self.geoCoder reverseGeocodeLocation:location
                        completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
                            
                            // 防错处理
                            if (error || placemarks.count == 0) {
                                NSLog(@"反地理编码错误:%@", error);
                                return;
                            }
                            
                            // 罗列出所有搜索到的地址名称
                            for (CLPlacemark *placemark in placemarks) {
                                NSLog(@"所有搜索到的地址名称:%@",placemark.name);
                            }
                            
                            //   一个placemark对应一个地理坐标,包含一个地方的信息(因为可能有多种结果,所有是一个数组,因此要给用户一个列表去选择)
                            CLPlacemark *placemark = [placemarks firstObject]; // 包含区,街道等信息的地标对象
                            NSLog(@"搜索到的第一个城市名:%@,搜索到的第一个地址名称:%@", placemark.locality, placemark.name);
                            
                            // 显示地址方法1:
                            // for (CLPlacemark *placemark in placemarks) {
                            // self.addressTextView.text = placemark.name; //具体地名
                            // }
                            
                            // 显示地址方法2:显示搜索到的第一个地址名称,到 addressTextView 中
                            self.addressTextView.text = [NSString stringWithFormat:@"%@", placemark.name];
                            
                            // 显示纬度(拼接字符串),到 latitudeTextField
                            self.latitudeTextField.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
                            // 显示经度(拼接字符串),到 longitudeUITextField
                            self.longitudeUITextField.text =[NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
                        }];
} #pragma mark - 退出键盘
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.view endEditing:YES];
} - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
} - (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
} @end

运行效果:

打印结果:

OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:河南省信阳市罗山县五道口
OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:河南省许昌市长葛市五道口
OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:内蒙古自治区巴彦淖尔市乌拉特前旗五道口
OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:山西省临汾市尧都区五道口
OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:辽宁省鞍山市岫岩满族自治县五道口
OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:山西省临汾市尧都区五道口
OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:山西省太原市晋源区五道口
OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:北京市海淀区五道口
OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:福建省泉州市德化县五道口
OC - 地理编码和反地理编码[16739:561135] 搜索到的第一个城市名:信阳市,搜索到的第一个地址名称:河南省信阳市罗山县五道口 OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:北京市
OC - 地理编码和反地理编码[16739:561135] 搜索到的第一个城市名:北京市,搜索到的第一个地址名称:北京市 OC - 地理编码和反地理编码[16739:561135] 所有搜索到的地址名称:甘棠镇
OC - 地理编码和反地理编码[16739:561135] 搜索到的第一个城市名:南宁市,搜索到的第一个地址名称:甘棠镇
【Swift语言】

import UIKit
import CoreLocation class ViewController: UIViewController {     @IBOutlet weak var addressTextView: UITextView!       // 地址
    @IBOutlet weak var latitudeTextField: UITextField!    // 纬度
    @IBOutlet weak var longitudeUITextField: UITextField! // 经度
    
    // MARK: - 懒加载
    lazy var geoCoder : CLGeocoder = {
        return CLGeocoder()
    }()
    
    // MARK: - 地理编码(地址->经纬度)
    @IBAction func geoCode(_ sender: UIButton) {
        
        let address = addressTextView.text
        
        geoCoder.geocodeAddressString(address!) { (placemarks : [CLPlacemark]?, error :Error?) in
            
            if error == nil{
                print("地理编码成功")
                
                guard let pls = placemarks else {return}
                let firstPL = pls.first
                
                self.addressTextView.text = firstPL?.name
                self.latitudeTextField.text = "\(firstPL?.location?.coordinate.latitude)"
                self.longitudeUITextField.text = "\(firstPL?.location?.coordinate.longitude)"
            }else {
                print("地理编码错误!!!")
            }
        }
    }
    
    // MARK: - 清空
    @IBAction func clearButton(_ sender: UIButton) {
        self.addressTextView.text = nil
        self.latitudeTextField.text = nil
        self.longitudeUITextField.text = nil
    }
    
    // MARK: - 反地理编码(经纬度->地址)
    @IBAction func reverseGeoCode(_ sender: UIButton) {
        
        let latitude = CLLocationDegrees(latitudeTextField.text!)
        let longitude = CLLocationDegrees(longitudeUITextField.text!)
        let location = CLLocation(latitude: latitude!, longitude: longitude!)
        
        geoCoder.reverseGeocodeLocation(location) { (placemarks :[CLPlacemark]?, error :Error?) in
            
            if error == nil{
                print("反地理编码成功")                 guard let pls = placemarks else {return}
                let firstPL = pls.first
                
                self.addressTextView.text = firstPL?.name
                self.latitudeTextField.text = "\(firstPL?.location?.coordinate.latitude)"
                self.longitudeUITextField.text = "\(firstPL?.location?.coordinate.longitude)"
            }else {
                print("反地理编码错误!!!")
            }
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }     override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

注:运行效果和打印结果省略


4.0 案例:获取当前位置名称

代码6:

编译环境:Xcode 8.0

模拟器版本:iOS 10

Swift版本:3.0

【OC 语言】
暂无,后期补上
【Swift语言】

import UIKit
import CoreLocation class ViewController: UIViewController {
    // 用于记录上次位置数据的变量
    var lastLoc: CLLocation?
    
    // 位置管理者的懒加载
    lazy var locationM : CLLocationManager = {
        
        let locationM : CLLocationManager = CLLocationManager() // 创建
        
        locationM.delegate = self // 遵守代理
        
        // 如果在iOS8.0之后, 需要额外的执行以下代码, 主动请求用户授权
        if #available(iOS 8.0, *) {
            // 请求前台定位授权(不要忘记在info.plist文件中, 配置对应的key)
            locationM.requestWhenInUseAuthorization()
            
            // 如果是iOS9.0之后, 当前授权状态是前台定位授权状态, 也想在后台获取用户的位置信息,那么需要满足以下条件
            // 1. 勾选后台模式   2. 设置以下属性为true(OC, 里面是YES)
            if #available(iOS 9.0, *) {
                locationM.allowsBackgroundLocationUpdates = true
            }
            locationM.desiredAccuracy = kCLLocationAccuracyBest // 设置精确度
        }
        return locationM
    }()
    
    // MARK: - 点击屏幕开始定位
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 定位: 标准定位服务 (gps/wifi/蓝牙/基站)
        locationM.startUpdatingLocation()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
} // MARK: - 代理
extension ViewController: CLLocationManagerDelegate {
    
    // 当获取到用户位置信息时调用
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
                 
        // 当前位置
        guard let newLocation = locations.last else {return}
        
        // 容错判断
        if newLocation.horizontalAccuracy < 0 { return }
        
        
        // 场景演示:打印当前用户的行走方向,偏离角度以及对应的行走距离
        // 例如:”北偏东 30度 方向,移动了 8米”
        
        // 实现步骤:
        // 1> 获取对应的方向偏向(例如”正东”,”东偏南”)
        // 2> 获取对应的偏离角度(并判断是否是正方向)
        // 3> 计算行走距离
        // 4> 打印信息
        
        // 1. 获取当前的行走航向 (算法: 根据航向course, 整除90, 判断出对应的方位)
        let courseStrs : [String] = ["北偏东", "东偏南", "南偏西", "西偏北"] // 定义数组,各个值为0,1,2,3
        let index : Int = Int(newLocation.course) / 90   // 将当前位置/90所得即是数组索引
        var courseStr : String = courseStrs[index]       // 当前的方向
        
        // 2. 行走的偏离角度
        let courseAngle : Int = Int(newLocation.course) % 90 // 取余
        
        // 如果能整除,就是正方向
        if Int(courseAngle) == 0 {
            let index = courseStr.characters.index(courseStr.startIndex, offsetBy: 1) // 截取数组的字符串的第1个
            courseStr = "正" + courseStr.substring(to: index)   // 拼接(正x方向)
        }
        
        // 3. 移动了多少米(计算当前位置和上一次的位置的距离)
        let lastLocation = lastLoc ?? newLocation
        let distance = newLocation.distance(from: lastLocation)
        lastLoc = newLocation
        
        // 4. 合并字符串, 打印( 例如:”北偏东 30度 方向,移动了 8米” )
        if courseAngle == 0{
            print("正\(courseStr)方向,移动了\(distance)米")
        }else{
            print("\(courseStr)\(courseAngle)度方向,移动了\(distance)米")
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("定位失败")
    }
}

打印结果:

南偏西78度方向,移动了0.0米
南偏西78度方向,移动了0.0米
南偏西78度方向,移动了0.0米
南偏西4度方向,移动了43.5456733705825米
东偏南85度方向,移动了4.16083969694213米
南偏西5度方向,移动了4.19352559351701米
南偏西1度方向,移动了3.98972251112523米
东偏南88度方向,移动了3.87999866791506米
东偏南87度方向,移动了3.84349812602442米
东偏南82度方向,移动了3.82326469279695米
东偏南79度方向,移动了3.79777809972005米

本文源码 Demo 详见 Github

https://github.com/shorfng/iOS_7.0_Device-Tools


作者:蓝田(Loto)
【作品发布平台】

简书

博客园

Gitbook(如果觉得文章太长,请阅读此平台发布的文章)

【代码托管平台】

Github

【如有疑问,请通过以下方式交流】

评论区回复

发送邮件shorfng@126.com

本文版权归作者和本网站共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,谢谢合作。


如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
  • 支付宝扫一扫 向我打赏

  • 你也可以微信 向我打赏

【iOS】7.4 定位服务->2.1.3.2 定位 - 官方框架CoreLocation 功能2:地理编码和反地理编码的更多相关文章

  1. 【iOS】7.4 定位服务->2.1.3.1 定位 - 官方框架CoreLocation 功能1:地理定位

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  2. 【iOS】7.4 定位服务->2.1.3.3 定位 - 官方框架CoreLocation 功能3:区域监听

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  3. 【iOS】7.4 定位服务->2.1.1 定位 - 官方框架CoreLocation: 请求用户授权

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  4. 【iOS】7.4 定位服务->2.1.2 定位 - 官方框架CoreLocation: CLLocationManager(位置管理器)

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  5. 【iOS】7.4 定位服务->2.1.4 定位 - 官方框架CoreLocation 案例:指南针效果

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  6. iOS 原生地图地理编码与反地理编码

    当我们要在App实现功能:输入地名,编码为经纬度,实现导航功能. 那么,我需要用到原生地图中的地理编码功能,而在Core Location中主要包含了定位.地理编码(包括反编码)功能. 在文件中导入 ...

  7. iOS地图 -- 地理编码和反地理编码

    地理编码和反地理编码 用到的类和方法 CLGeocoder --> 地理编码管理器 - (void)geocodeAddressString:(NSString *)addressString ...

  8. 【iOS】7.4 定位服务->3.1 地图框架MapKit 功能1:地图展示

    > 本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. --- > 本文相关目录: ================== 所属文集:[[ ...

  9. 【iOS】7.4 定位服务->3.2 地图框架MapKit 功能2:路线规划(导航)

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

随机推荐

  1. 实现过程全纪录——自己写一个“微信朋友圈”(包括移动端与PC端)

    一.朋友圈的基本单元--动态 首先定义一个自定义控件用来显示每条动态. 二.运行效果 三.核心解读 PushedMessage 有个PushIndex属性,表示发送消息的index,从0开始递增.每个 ...

  2. UWP 律师信息 MVVM 2.0版本

    由于1.0版本存在一个很大的BUG,一直也没有找到问题所在,后来,一位在微软的朋友说,他们的测试小妹给出的结果是框架的问题,所以,就直接整体重构了代码,也布局设计上,由跳转页面变为了UWP常见的左侧列 ...

  3. Node v0.12.5 稳定版发布

    Node v0.12.5 稳定版发布了,该版本改进记录主要包括: openssl: upgrade to 1.0.1o (Addressing multiple CVEs) npm: upgrade ...

  4. gulp源码解析(二)—— vinyl-fs

    在上一篇文章我们对 Stream 的特性及其接口进行了介绍,gulp 之所以在性能上好于 grunt,主要是因为有了 Stream 助力来做数据的传输和处理. 那么我们不难猜想出,在 gulp 的任务 ...

  5. Ubuntu 修改时区

    1. 使用命令行 sudo tzselect 根据提示完成修改 2.修改~/.profile文件 添加: TZ='Asia/Shanghai'; export TZ 注销后重新登陆生效

  6. modprobe和insmod的区别

    linux设备驱动有两种加载方式insmod和modprobe,下面谈谈它们用法上的区别1.insmod一次只能加载特定的一个设备驱动,且需要驱动的具体地址.写法为:        insmod dr ...

  7. Java异常处理机制以及try-catch-finally-return执行顺序

    一,简单描述: 当出现程序无法控制的外部环境问题(用户提供的文件不存在,文件内容损坏,网络不可用...)时,JAVA就会用异常对象来描述. 二,JAVA中用2种方法处理异常: 1.在发生异常的地方直接 ...

  8. 【踩坑速记】MIUI系统BUG,调用系统相机拍照可能会带给你的一系列坑,将拍照适配方案进行到底!

    一.写在前面 前几天也是分享了一些学习必备干货(还没关注的,赶紧入坑:传送门),也好久没有与大家探讨技术方案了,心里也是挺痒痒的,这不,一有点闲暇之时,就迫不及待把最近测出来的坑分享给大家. 提起An ...

  9. 最简单的排序算法之一冒泡排序----js实现

    1. 算法步骤 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.这步做完后,最后的元素会是最大的数. 针对所有的元素重复以上的步骤, ...

  10. STAR法则

    现在相信大部分跳槽的朋友都已经将工作辞了,正在找工作的这个漩涡中,还没辞掉的可能也快了,找工作的这段时间是一个非常考验你的扛打击能力的时候.像网上投了几十家简历,只有几家邀请面试的,其他都是连面试阶段 ...