【iOS】7.4 定位服务->2.1.3.2 定位 - 官方框架CoreLocation 功能2:地理编码和反地理编码
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正。
本文相关目录:
================== 所属文集:【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(如果觉得文章太长,请阅读此平台发布的文章)
【代码托管平台】
【如有疑问,请通过以下方式交流】
① 评论区回复
② 发送邮件至 shorfng@126.com
本文版权归作者和本网站共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,谢谢合作。
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
支付宝扫一扫 向我打赏

你也可以微信 向我打赏

【iOS】7.4 定位服务->2.1.3.2 定位 - 官方框架CoreLocation 功能2:地理编码和反地理编码的更多相关文章
- 【iOS】7.4 定位服务->2.1.3.1 定位 - 官方框架CoreLocation 功能1:地理定位
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【iOS】7.4 定位服务->2.1.3.3 定位 - 官方框架CoreLocation 功能3:区域监听
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【iOS】7.4 定位服务->2.1.1 定位 - 官方框架CoreLocation: 请求用户授权
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【iOS】7.4 定位服务->2.1.2 定位 - 官方框架CoreLocation: CLLocationManager(位置管理器)
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【iOS】7.4 定位服务->2.1.4 定位 - 官方框架CoreLocation 案例:指南针效果
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- iOS 原生地图地理编码与反地理编码
当我们要在App实现功能:输入地名,编码为经纬度,实现导航功能. 那么,我需要用到原生地图中的地理编码功能,而在Core Location中主要包含了定位.地理编码(包括反编码)功能. 在文件中导入 ...
- iOS地图 -- 地理编码和反地理编码
地理编码和反地理编码 用到的类和方法 CLGeocoder --> 地理编码管理器 - (void)geocodeAddressString:(NSString *)addressString ...
- 【iOS】7.4 定位服务->3.1 地图框架MapKit 功能1:地图展示
> 本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. --- > 本文相关目录: ================== 所属文集:[[ ...
- 【iOS】7.4 定位服务->3.2 地图框架MapKit 功能2:路线规划(导航)
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
随机推荐
- 《JAVASCRIPT高级程序设计》原生拖放和媒体元素
一.原生拖放 最早在网页中引入javascript拖放功能的是IE4,当时,网页中只有两种对象可以拖放:图像和某些文本.而现在,几乎网页中的任何元素都可以拖放以及作为放置目标.下面介绍一些与拖放相关的 ...
- 去除android或者iOS系统默认的一些样式总结
ios系统中元素被触摸时产生的半透明灰色遮罩怎么去掉 iOS用户点击一个链接,会出现一个半透明灰色遮罩, 如果想要禁用,可设置-webkit-tap-highlight-color的alpha值为0, ...
- java实现简单的单点登录_转
摘要:单点登录(SSO)的技术被越来越广泛地运用到各个领域的软件系统当中.本文从业务的角度分析了单点登录的需求和应用领域:从技术本身的角度分析了单点登录技术的内部机制和实现手段,并且给出Web-SSO ...
- arcpy.mapping常用四大件-Layer
arcpy.mapping常用四大件-Layer by 李远祥 图层是地图里面非常重要的组成,几乎所有的制图显示都与图层有关.首先它是连接数据与符号渲染的重要桥梁,其次在出版地图中,图层又与图例关联在 ...
- Webappbuilder自定义widget模板
Webappbuilder自定义widget模板 by 李远祥 到\\widgets\samplewidgets目录下拷贝 CustomWidgetTemplate 文件并重命名为MyWidget 设 ...
- 用keychain这个特点来保存设备唯一标识。
由于IOS系统存储的数据都是在sandBox里面,一旦删除App,sandBox也不复存在.好在有一个例外,那就是keychain(钥匙串). 通常情况下,IOS系统用NSUserDefaults存储 ...
- handlebars使用总结
对自己使用handlebars做一个小总结,以后忘记了,好有地方看一下,不会用的小伙伴也可以借鉴一下,写的不好. 使用 Handlebars的安装是比较简单和方便的;handlebars是一个纯JS库 ...
- JAVA设计模式:模板设计模式
1.模板设计模式,是为了体现继承的作用.它主要的作用就是在类中定义一些公共的方法和标准,而其具体的实现则叫给其子类来根据子类具体的行为来实现:因为模板设计模式中必经还有一些自己的方法不是抽象的方法,只 ...
- gridView 主从表实现
1.主要代码: private void Form2_Load(object sender, EventArgs e) { DataTable dt1 = new DataTable("dt ...
- jeesite简单入口分析
这两天要开新项目 , 准备使用比较受欢迎的 jeesite框架 . jeesite是一个写好的网站 , 用到的框架比较多 具体请看 -- > github链接 下载下来之后 , 手动把maven ...

