知识点:
1.CoreLocation框架—负责定位的(手机的)位置。用于地理定位
2.MapKit.framework—系统自带的框架,地图展示,
3.ios7 中:系统会自动申请用户位置权限。
CoreLocation中使用
CLLocationManager对象来做用户定位,
CoreLocation框架中所有数据类型的前缀都是
CL
定位的类(位置管理器最好懒加载创建,强引用):CLLocationManager ,用alloc init,创建 ,监听用代理,实现代理方法, 开始更新用户的位置【位置管理器的对象 startUpdatingLocation】,
用来表示经纬度的结构体——CLLocationCoordinate2D
latitude —纬度 longitude — 经度 course —朝向 timeStamp —更新的点的时间, 测试楼层--floor
4.ios8之后,要做一个判断,如果是,要申请用户权限。代理方法---判断授权状态,status 在Info。plist文件中配置Key值,(当用户在前台还是后台的时候。 请求数据 request。。。。)---代理方法---判断授权状态,
5.调整位置的经纬度—deBug 中的location;
6.位置管理器的常见属性
当用户移动了多长的距离之后,才更新用户的位置(米),对象.distanceFilter =10;
定位精度(精度越高越费电):对象.desiredAccuracy =
kCLLocationAccuracyBestForNavigation;
extern const CLLocationAccuracy kCLLocationAccuracyBestForNavigation;
导航使用最好进度
// extern const CLLocationAccuracy kCLLocationAccuracyBest;
最高精度
// extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters; 10M
// extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters; 100M
// extern const CLLocationAccuracy kCLLocationAccuracyKilometer; 1000M
// extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters; 10M
// extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters; 100M
// extern const CLLocationAccuracy kCLLocationAccuracyKilometer; 1000M
// extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers; 3000M
导航的使用场景要用activityType =定位数据的用途
self.
locationManager.
activityType =
CLActivityTypeFitness;
// CLActivityTypeOther = 1,
// CLActivityTypeAutomotiveNavigation, // 汽车导航
// CLActivityTypeFitness, // 步行导航
// CLActivityTypeOtherNavigation // 其他导航 , 比如轮船 , 火车 , 飞机
// CLActivityTypeOther = 1,
// CLActivityTypeAutomotiveNavigation, // 汽车导航
// CLActivityTypeFitness, // 步行导航
// CLActivityTypeOtherNavigation // 其他导航 , 比如轮船 , 火车 , 飞机
//
CLLocation用来表示某个位置的地理信息,比如经纬度、海拔等等。常见属性
CLLocationCoordinate2D coordinate;表示经纬度
CLLocationDistance altitude;表示海拔
CLLocationDirection course;表示路线,航向(取值范围是0.0° ~ 359.9°,0.0°代表真北方向)
CLLocationSpeed speed;表示行走速度(单位是m/s)
- 用- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location方法可以计算2个位置之间的距离
- 计算两个时间点之间的时间差的方法: self.sumTime += [currentLocation.timestamp timeIntervalSinceDate:self.preLocation.timestamp];
计算平均速度案例:
- (
void)locationManager:(
CLLocationManager *)manager didUpdateLocations:(
NSArray<
CLLocation *> *)locations
{
{
CLLocation *currentLocation = locations.
lastObject;
if ( self. preLocation == nil) {
self. preLocation = currentLocation;
return;
}
// 计算地图上两点之间的距离 , 以米为单位的
self.
sumDistance += [currentLocation
distanceFromLocation:
self.
preLocation];
self.
sumTime += [currentLocation.
timestamp
timeIntervalSinceDate:
self.
preLocation.
timestamp];
// 计算平均速度
CGFloat avgSpeed = self. sumDistance / self. sumTime;
NSLog(
@"
总距离
:%lf,
总时间
:%lf,
平均速度
:%lf",
self.
sumDistance,
self.
sumTime,avgSpeed);
}
CLHeading:用来表示方向相关的数据
//
更新用户的方向
[
self.
locationManager
startUpdatingHeading];
- @property(readonly, nonatomic) CLLocationDirection magneticHeading
- 磁北偏移量, 0度表示磁北, 0 – 359.9
- 磁北: 磁场北极,是指南针所指的北
- @property(readonly, nonatomic) CLLocationDirection trueHeading
- 真北偏移量, 0度表示真北
- 真北:地理北极, 是地图或者地球仪上所有经线的起始点
设置指南针案例:
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface
ViewController ()<
CLLocationManagerDelegate>
@property (
weak,
nonatomic)
IBOutlet
UIImageView *compass;指南针
@property(
nonatomic,
strong)
CLLocationManager * locationManager ;
@end
@implementation ViewController
#pragma mark - 懒加载 要在真机上试
-( CLLocationManager *)locationManager{
if (! _locationManager) {
_locationManager = [[ CLLocationManager alloc] init];
_locationManager. delegate = self;
}
return _locationManager;
@end
@implementation ViewController
#pragma mark - 懒加载 要在真机上试
-( CLLocationManager *)locationManager{
if (! _locationManager) {
_locationManager = [[ CLLocationManager alloc] init];
_locationManager. delegate = self;
}
return _locationManager;
}
- (
void)viewDidLoad {
[
super
viewDidLoad];
// 获取用户朝向,没有涉及用户的隐私,不需要请求用户的授权
// 更新用户的方向
[ self. locationManager startUpdatingHeading];
}
#pragma mark - 代理方法
// 当手机的朝向发生改变的时候执行该代理方法 newHeading :用于描述方位的类
-( void)locationManager:( CLLocationManager *)manager didUpdateHeading:( CLHeading *)newHeading{
// 相对于磁北极偏移量 :(0.0 - 359.9 degrees)
// newHeading.magneticHeading
// 相对于真北极的偏移量
// newHeading.trueHeading;(0.0 - 359.9 degrees)
double degrees = newHeading. magneticHeading;
// 角度值转换弧度值
CGFloat angle = degrees / ( 180 / M_PI);
// 由于偏移方向与 transform 的方向是相反的
self. compass. transform = CGAffineTransformMakeRotation(-angle);
// 获取用户朝向,没有涉及用户的隐私,不需要请求用户的授权
// 更新用户的方向
[ self. locationManager startUpdatingHeading];
}
#pragma mark - 代理方法
// 当手机的朝向发生改变的时候执行该代理方法 newHeading :用于描述方位的类
-( void)locationManager:( CLLocationManager *)manager didUpdateHeading:( CLHeading *)newHeading{
// 相对于磁北极偏移量 :(0.0 - 359.9 degrees)
// newHeading.magneticHeading
// 相对于真北极的偏移量
// newHeading.trueHeading;(0.0 - 359.9 degrees)
double degrees = newHeading. magneticHeading;
// 角度值转换弧度值
CGFloat angle = degrees / ( 180 / M_PI);
// 由于偏移方向与 transform 的方向是相反的
self. compass. transform = CGAffineTransformMakeRotation(-angle);
}
CLRegion:区域
子类:CLCircularRegion 表示圆形范围:属性:radius 和center
CLLocationCoordinate2D:表示是一个用来表示经纬度的结构体,
typedef struct {
CLLocationDegrees latitude; // 纬度
CLLocationDegrees longitude; // 经度
} CLLocationCoordinate2D;
一般用CLLocationCoordinate2DMake函数来创建
CLLocationCoordinate2D
7.计算地图上两点之间的距离(CLLocation
对象) = locations.lastObject;
distanceFromLocation:方法计算两点间的距离
8.监听用户区域( 请求总是授权):【对象 requestAlways
Authorization】表示应用不管在前台还是后台,都可以监听用户的地理位置,开发者在Info.plist中设置NSLocationUsageDescription说明定位的目的
当要监听用户区域改变
,
那么必须请求总是授权
requestWhenInUseAuthorization
只有当前应用在前台的时候
,
才需要使用用户的位置
需要在
info.plist
文件中配置
NSLocationWhenInUseUsageDescription key
来说明使用用户位置的原因
开始监听用户的区域:【 startMonitorngForRegion:】用代理方法(当用户进入监听区域的时候,执行代理方法 didEnterRegion: 离开的时候执行:didExitRegion:)
ClRegion:描述地图上的一块区域的,通常用他的子类 CLCircularRegion initWithCenter:创建
9.指南针:要生成证书 fix Issue
获取用户的朝向,没有涉及到用户的隐私。不需要请求用户授权,【对象 startUpdatingHeadIng】——更新用户方向。遵守代理方法 didUpdateHeading:
newsHeading.magneticHeading ——相对于磁北极:(取值范围:0.0——359.9 degrees角度值—要转为弧度制 degrees / (180/M_PI))在设置指南针的偏移量:transfuse ----用make,弧度值为负的,因为是方向是相反的
相对于真北极的偏移量--------newsHeading.trueHeading
10.CLGeocoder: 可以完成“地理编码”和“反地理编码” (创建)地理编码器
地理编码:把地名转换成经纬度
反地理编码:把经纬度信息转换成地名
地理编码方法:
- (
void)geocodeAddressString:(
NSString *)addressString completionHandler:(
CLGeocodeCompletionHandler)completionHandler;
这个方法会访问苹果位置的服务器来返回数据。
CLPlaceMark :地标—— 描述了地理发经纬度,地名,省,市,区,街道。
- CLPlacemark的字面意思是地标,封装详细的地址位置信息
- @property (nonatomic, readonly) CLLocation *location;
- 地理位置
- @property (nonatomic, readonly) CLRegion *region;
- 区域
- @property (nonatomic, readonly) NSDictionary *addressDictionary;
- 详细的地址信息
- @property (nonatomic, readonly) NSString *name;
- 地址名称
- @property (nonatomic, readonly) NSString *locality;
- 城市
例子:
#import
"ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()
@property ( weak, nonatomic) IBOutlet UITextField *address;
@property ( weak, nonatomic) IBOutlet UITextField *latitude;
@property ( weak, nonatomic) IBOutlet UITextField *longitude;
@property ( weak, nonatomic) IBOutlet UILabel *latitudeLable;
@property ( weak, nonatomic) IBOutlet UILabel *longitudeLable;
@property ( weak, nonatomic) IBOutlet UILabel *addressLable;
@end
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()
@property ( weak, nonatomic) IBOutlet UITextField *address;
@property ( weak, nonatomic) IBOutlet UITextField *latitude;
@property ( weak, nonatomic) IBOutlet UITextField *longitude;
@property ( weak, nonatomic) IBOutlet UILabel *latitudeLable;
@property ( weak, nonatomic) IBOutlet UILabel *longitudeLable;
@property ( weak, nonatomic) IBOutlet UILabel *addressLable;
@end
@implementation ViewController
#pragma mark -
地理编码
- ( IBAction)Geogidute:( id)sender {
NSString * adress = self. address. text;
if (adress. length == 0) {
NSLog( @" 请输入地名 ");
return;
}
// 地理编码器 创建
CLGeocoder * geocoder = [[ CLGeocoder alloc] init];
// 地理编码:把地名转换成经纬度 有个方法 这个方法会访问苹果位置的服务器 , 来返回数据
[geocoder geocodeAddressString:adress completionHandler:^( NSArray< CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// CLPlacemark 地标:描述了地理的经纬度,地名:省市区
// 要遍历这个地标,因为地球上相同名字的地方会有很多个
[placemarks enumerateObjectsUsingBlock:^( CLPlacemark * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// 经纬度
CLPlacemark * placemark = obj;
CLLocationCoordinate2D coordinate = placemark. location. coordinate;
// 名称
NSLog( @"%lf,%lf",coordinate. latitude,coordinate. longitude);
NSLog( @"%@",placemark. name);
NSLog( @"%@ 省 ( 直辖市 ) %@ 市 %@ 区 ",placemark. administrativeArea,placemark. locality,placemark. subLocality);
self. latitudeLable. text = [ NSString stringWithFormat: @"%lf",coordinate. latitude];
self. longitudeLable. text = [ NSString stringWithFormat: @"%lf",coordinate. longitude];
self. addressLable. text = placemark. name;
}];
}];
- ( IBAction)Geogidute:( id)sender {
NSString * adress = self. address. text;
if (adress. length == 0) {
NSLog( @" 请输入地名 ");
return;
}
// 地理编码器 创建
CLGeocoder * geocoder = [[ CLGeocoder alloc] init];
// 地理编码:把地名转换成经纬度 有个方法 这个方法会访问苹果位置的服务器 , 来返回数据
[geocoder geocodeAddressString:adress completionHandler:^( NSArray< CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// CLPlacemark 地标:描述了地理的经纬度,地名:省市区
// 要遍历这个地标,因为地球上相同名字的地方会有很多个
[placemarks enumerateObjectsUsingBlock:^( CLPlacemark * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// 经纬度
CLPlacemark * placemark = obj;
CLLocationCoordinate2D coordinate = placemark. location. coordinate;
// 名称
NSLog( @"%lf,%lf",coordinate. latitude,coordinate. longitude);
NSLog( @"%@",placemark. name);
NSLog( @"%@ 省 ( 直辖市 ) %@ 市 %@ 区 ",placemark. administrativeArea,placemark. locality,placemark. subLocality);
self. latitudeLable. text = [ NSString stringWithFormat: @"%lf",coordinate. latitude];
self. longitudeLable. text = [ NSString stringWithFormat: @"%lf",coordinate. longitude];
self. addressLable. text = placemark. name;
}];
}];
}
反地理编码方法
- (
void)reverseGeocodeLocation:(
CLLocation *)location completionHandler:(
CLGeocodeCompletionHandler)completionHandler;
例子:
#import
"ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()
@property ( weak, nonatomic) IBOutlet UITextField *address;
@property ( weak, nonatomic) IBOutlet UITextField *latitude;
@property ( weak, nonatomic) IBOutlet UITextField *longitude;
@property ( weak, nonatomic) IBOutlet UILabel *latitudeLable;
@property ( weak, nonatomic) IBOutlet UILabel *longitudeLable;
@property ( weak, nonatomic) IBOutlet UILabel *addressLable;
@end
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()
@property ( weak, nonatomic) IBOutlet UITextField *address;
@property ( weak, nonatomic) IBOutlet UITextField *latitude;
@property ( weak, nonatomic) IBOutlet UITextField *longitude;
@property ( weak, nonatomic) IBOutlet UILabel *latitudeLable;
@property ( weak, nonatomic) IBOutlet UILabel *longitudeLable;
@property ( weak, nonatomic) IBOutlet UILabel *addressLable;
@end
@implementation ViewController
#pragma mark -
反地理编码
- ( IBAction)reverseGeogidute:( id)sender {
NSString *latitudeStr = self. latitude. text;
NSString *longitudeStr = self. longitude. text;
if (latitudeStr. length == 0) {
NSLog( @" 请输入纬度信息 ");
return;
}
if (longitudeStr. length == 0) {
NSLog( @" 请输入经度信息 ");
return;
}
// 创建地理编码器
CLGeocoder * geocoder = [[ CLGeocoder alloc] init];
// 创建位置对象
CLLocation * location = [[ CLLocation alloc] initWithLatitude:latitudeStr. doubleValue longitude:longitudeStr. doubleValue];
// 反地理编码
[ geocoder reverseGeocodeLocation:location completionHandler:^( NSArray< CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
[placemarks enumerateObjectsUsingBlock:^( CLPlacemark * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// 地标
CLPlacemark * placemark = obj;
// 经纬度
CLLocationCoordinate2D coordinate = placemark. location. coordinate;
NSLog( @"%lf,%lf",coordinate. latitude,coordinate. longitude);
NSLog( @"%@",placemark. name);
NSLog( @"%@ 省 ( 直辖市 ) %@ 市 %@ 区 ",placemark. administrativeArea,placemark. locality,placemark. subLocality);
self. latitudeLable. text = [ NSString stringWithFormat: @"%lf",coordinate. latitude];
self. longitudeLable. text = [ NSString stringWithFormat: @"%lf",coordinate. longitude];
self. addressLable. text = placemark. name;
}];
}];
- ( IBAction)reverseGeogidute:( id)sender {
NSString *latitudeStr = self. latitude. text;
NSString *longitudeStr = self. longitude. text;
if (latitudeStr. length == 0) {
NSLog( @" 请输入纬度信息 ");
return;
}
if (longitudeStr. length == 0) {
NSLog( @" 请输入经度信息 ");
return;
}
// 创建地理编码器
CLGeocoder * geocoder = [[ CLGeocoder alloc] init];
// 创建位置对象
CLLocation * location = [[ CLLocation alloc] initWithLatitude:latitudeStr. doubleValue longitude:longitudeStr. doubleValue];
// 反地理编码
[ geocoder reverseGeocodeLocation:location completionHandler:^( NSArray< CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
[placemarks enumerateObjectsUsingBlock:^( CLPlacemark * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// 地标
CLPlacemark * placemark = obj;
// 经纬度
CLLocationCoordinate2D coordinate = placemark. location. coordinate;
NSLog( @"%lf,%lf",coordinate. latitude,coordinate. longitude);
NSLog( @"%@",placemark. name);
NSLog( @"%@ 省 ( 直辖市 ) %@ 市 %@ 区 ",placemark. administrativeArea,placemark. locality,placemark. subLocality);
self. latitudeLable. text = [ NSString stringWithFormat: @"%lf",coordinate. latitude];
self. longitudeLable. text = [ NSString stringWithFormat: @"%lf",coordinate. longitude];
self. addressLable. text = placemark. name;
}];
}];
}
系统地图。
1.地图的基本使用
控件栏里的Map View 需要导入对应框架 mapKit.framework 动态库里设置
导入头文件<mapKit>
- MapKit框架中所有数据类型的前缀都是MK
- MapKit有一个比较重要的UI控件 :MKMapView,专门用于地图显示
- 可以通过设置MKMapView的mapViewType设置地图类型
- MKMapTypeStandard :普通地图
- MKMapTypeSatellite :卫星云图
- MKMapTypeHybrid :混合地国
跟踪显示用户的位置 userTrackingMode 首先要用户授权,
- 设置MKMapView的userTrackingMode属性可以跟踪显示用户的当前位置
- MKUserTrackingModeNone :不跟踪用户的位置
- MKUserTrackingModeFollow :跟踪并在地图上显示用户的当前位置
- MKUserTrackingModeFollowWithHeading :跟踪并在地图上显示用户的当前位置,地图会跟随用户的前进方向进行旋转
- MKMapView可以设置一个代理对象,用来监听地图的相关行为
- 常见的代理方法有
- - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation;
- 一个位置更改默认只会调用一次,不断监测用户的当前位置
- 每次调用,都会把用户的最新位置(userLocation参数)传进来
- - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated;
- 地图的显示区域即将发生改变的时候调用
- - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
- 地图的显示区域已经发生改变的时候调用
- #pragma mark -用户更新位置时执行
/// iOS7 中用于显示用户所在地图区域,iOS8以后,可以修改默认的跨度.
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
// MKCoordinateRegion 用于描述地图一块区域
// 跨度
MKCoordinateSpan span = MKCoordinateSpanMake(0.01,0.01);
// 区域
MKCoordinateRegion region = MKCoordinateRegionMake(userLocation.location.coordinate, span);
// 设置地图的显示区域
[ self.mapView setRegion:region];
}
添加大头针:系统自带的 MKpointAnnotation大头针
模型(标注)——需要经纬度(大头针的点位置)。设置标题title,subTitle子标题在添加到地图上去大头针
自定义大头针:(可以设置样式,大头针颜色(pinColor只有三种颜色 ---canShowCallout这个属性可以出现前面默认设置好的泡泡视图,因为这边涉及到重用。设置泡泡视图的辅助视图用到的属性:left/rightCalloutAccessoryView:button或自定义控件。 ios9新增属性:pinTintColor(各种颜色)),ios8增加的属性:坠落动画:animatesDrop为YES。在代理方法中,mapView:viewForAnnotation:定义 ,返回大头针视图;如果返回nil 就是默认大头针,
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView: self. view];
if( 模型对象 iskindofclass :模型 class)
自定义大头针设置样式
:定义大头针模型:新建一个类继承自NSObject。在类中,遵从大头针模型协议只会生成get方法。:导入mapkit框架,删除foundation框架。设置属性,枚举类型,
点转换成经纬度的方法:
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView: self. view];
CLLocationCoordinate2D coodinate = [
self.
mapView
convertPoint:point
toCoordinateFromView:
self.
view];
经纬度转换成点的方法: - (
CGPoint)convertCoordinate:(
CLLocationCoordinate2D)coordinate toPointToView:(
nullable
UIView *)view;
MKMapItem也是地标(创建地图的地标对象)。只有两种使用场景:1.跳转原生地图,2. 计算线路
1.跳转原生地图:案例
#import
"ViewController.h"
#import <MapKit/MapKit.h>
@interface ViewController ()
@property ( weak, nonatomic) IBOutlet UITextField *startAddress;
@property ( weak, nonatomic) IBOutlet UITextField *endAddress;
@end
@implementation ViewController
- ( IBAction)lookHeading:( id)sender {
NSString * startStr = self. startAddress. text;
NSString * endStr = self. endAddress. text;
// 判断用户是否输入
if (startStr. length == 0) {
NSLog( @" 请输入始发地 ");
return;
}
if (endStr. length == 0) {
NSLog( @" 请输入目的地 ");
return;
}
// 地理编码
CLGeocoder * geocoder = [[ CLGeocoder alloc] init];
[ geocoder geocodeAddressString:startStr completionHandler:^( NSArray< CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// 多个对象应该如何过滤呢 ?
// 1. 一般我们遍历 , 然后所在位置是否在用户所在区域
// 2. 有时候我们也会选用距离用户最近的点
CLPlacemark * placemark = placemarks. lastObject;
// MKMapItem 使用场景 : 1. 跳转原生地图 2. 计算线路
// [MKMapItem mapItemForCurrentLocation] 当前用户的位置 . 注意如果使用它就必须先请求用户位置权限
// 创建一个地图的地标对象
MKPlacemark * startPlacemark = [[ MKPlacemark alloc] initWithPlacemark:placemark];
MKMapItem * startMapItem = [[ MKMapItem alloc] initWithPlacemark:startPlacemark];
[ geocoder geocodeAddressString:endStr completionHandler:^( NSArray< CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
CLPlacemark * placemark = placemarks. lastObject;
MKPlacemark * endPlacemark = [[ MKPlacemark alloc] initWithPlacemark:placemark];
MKMapItem * endMapItem = [[ MKMapItem alloc] initWithPlacemark:endPlacemark];
// 这个方法只能在地图标注一个点
// [startMapItem openInMapsWithLaunchOptions:<#(nullable NSDictionary<NSString *,id> *)#>]
// MKLaunchOptionsDirectionsModeKey 指定导航模式
// NSString * const MKLaunchOptionsDirectionsModeDriving; 驾车
// NSString * const MKLaunchOptionsDirectionsModeWalking; 步行
// NSString * const MKLaunchOptionsDirectionsModeTransit; 动车或者高铁
NSDictionary * lauchOptions = @{ MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeWalking }; // 步行
// 打开原生地图进行导航
[ MKMapItem openMapsWithItems: @[startMapItem,endMapItem ] launchOptions:lauchOptions];
}];
}];
#import <MapKit/MapKit.h>
@interface ViewController ()
@property ( weak, nonatomic) IBOutlet UITextField *startAddress;
@property ( weak, nonatomic) IBOutlet UITextField *endAddress;
@end
@implementation ViewController
- ( IBAction)lookHeading:( id)sender {
NSString * startStr = self. startAddress. text;
NSString * endStr = self. endAddress. text;
// 判断用户是否输入
if (startStr. length == 0) {
NSLog( @" 请输入始发地 ");
return;
}
if (endStr. length == 0) {
NSLog( @" 请输入目的地 ");
return;
}
// 地理编码
CLGeocoder * geocoder = [[ CLGeocoder alloc] init];
[ geocoder geocodeAddressString:startStr completionHandler:^( NSArray< CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// 多个对象应该如何过滤呢 ?
// 1. 一般我们遍历 , 然后所在位置是否在用户所在区域
// 2. 有时候我们也会选用距离用户最近的点
CLPlacemark * placemark = placemarks. lastObject;
// MKMapItem 使用场景 : 1. 跳转原生地图 2. 计算线路
// [MKMapItem mapItemForCurrentLocation] 当前用户的位置 . 注意如果使用它就必须先请求用户位置权限
// 创建一个地图的地标对象
MKPlacemark * startPlacemark = [[ MKPlacemark alloc] initWithPlacemark:placemark];
MKMapItem * startMapItem = [[ MKMapItem alloc] initWithPlacemark:startPlacemark];
[ geocoder geocodeAddressString:endStr completionHandler:^( NSArray< CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
CLPlacemark * placemark = placemarks. lastObject;
MKPlacemark * endPlacemark = [[ MKPlacemark alloc] initWithPlacemark:placemark];
MKMapItem * endMapItem = [[ MKMapItem alloc] initWithPlacemark:endPlacemark];
// 这个方法只能在地图标注一个点
// [startMapItem openInMapsWithLaunchOptions:<#(nullable NSDictionary<NSString *,id> *)#>]
// MKLaunchOptionsDirectionsModeKey 指定导航模式
// NSString * const MKLaunchOptionsDirectionsModeDriving; 驾车
// NSString * const MKLaunchOptionsDirectionsModeWalking; 步行
// NSString * const MKLaunchOptionsDirectionsModeTransit; 动车或者高铁
NSDictionary * lauchOptions = @{ MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeWalking }; // 步行
// 打开原生地图进行导航
[ MKMapItem openMapsWithItems: @[startMapItem,endMapItem ] launchOptions:lauchOptions];
}];
}];
}