一.实现一次定位(实际上就是持续定为,完成定位更新的时候停止定位,就成了一次定位)
@interface ViewController ()<CLLocationManagerDelegate>
/**
位置管理器
*/
@property (nonatomic,strong)CLLocationManager *locationManager;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
//1. 创建一个CLLocationManager对象
self.locationManager = [CLLocationManagernew];
//2. 请求授权 --> iOS8以后需要授权并配置plist键值,NSLocationWhenInUseUsageDescription:授权需要填加的值, Localization native development region:en;
//为了防止iOS7奔溃,需要做判断: 2种方式: 1.判断能否响应 2.判断系统版本
//if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { }
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
//当程序在前台,看见的时候调用
[self.locationManager requestWhenInUseAuthorization];
}
//3. 设置代理-->来获取用户定位的数据
self.locationManager.delegate =self;
//4. 开始定位
[self.locationManager startUpdatingLocation];
}
#pragma mark 定位的代理方法
/**
当完成位置更新的时候调用
locations: 位置信息数据
此方法会频繁调用.非常耗电
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
//locations : 包含了经纬度, 速度等信息
NSLog(@"locations: %@", locations);
//5. 停止定位( 如果不 停止定为就是持续定位)
[self.locationManager stopUpdatingLocation];
}
@end
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
/**
@interface ViewController ()<CLLocationManagerDelegate>
/**
位置管理器
*/
@property (nonatomic,strong)CLLocationManager *locationManager;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
//1. 创建一个CLLocationManager对象
self.locationManager = [CLLocationManagernew];
//2. 请求授权 --> iOS8以后需要授权并配置plist键值
if ([self.locationManagerrespondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[self.locationManagerrequestWhenInUseAuthorization];
}
//3. 设置代理-->来获取用户定位的数据
self.locationManager.delegate =self;
//4. 开始定位
[self.locationManagerstartUpdatingLocation];
/**
持续定位:其实就是希望定位的时候,可以节省电量.
距离筛选器:当用户发生一定的位置改变之后,再调用代理方法
*/
//5.距离筛选器:单位米 -->主要是通过降低代理方法的调用频率,达到省电目的
//Filter:筛选 /过滤
// 如果设置了10,那么发生了10米以上的变化时才会调用
self.locationManager.distanceFilter =10;
//6. 预期精准度:
//desired: 期望/预期
//Accuracy: 精准度
/**
手机中定位方法: GPS / WIFI /移动基站 /北斗(iPhone中没有)
主要是通过GPS来定位: GPS是跟全球24颗卫星在进行通讯.可以通过减少计算量来达到省电的目的
*/
/**
精准度
CLLocationAccuracy kCLLocationAccuracyBestForNavigation//最好的为导航
CLLocationAccuracy kCLLocationAccuracyBest;//最好的
CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;//10米
CLLocationAccuracy kCLLocationAccuracyHundredMeters;//百米
CLLocationAccuracy kCLLocationAccuracyKilometer;//1千米
CLLocationAccuracy kCLLocationAccuracyThreeKilometers;3千米
*/
self.locationManager.desiredAccuracy =kCLLocationAccuracyKilometer;
//7. 比较2个位置之间的距离比较的是直线距离
// 北京到西安的距离
CLLocation *location1 = [[CLLocationalloc]initWithLatitude:40.06longitude:116.39];
CLLocation *location2 = [[CLLocationalloc]initWithLatitude:34.27longitude:108.93];
CLLocationDistance distance = [location1 distanceFromLocation:location2];
NSLog(@"distance: %f",distance /1000);
}
#pragma mark 定位的代理方法
/**
当完成位置更新的时候调用
locations: 位置信息数据
此方法会频繁调用.非常耗电
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
//locations : 包含了经纬度, 速度等信息
NSLog(@"locations: %@", locations);
// CLLocation: 位置对象
CLLocation *location = locations.lastObject;
//CLLocationCoordinate2D coordinate : 2D位置坐标:
//CLLocationDegrees latitude : 纬度
//CLLocationDegrees longitude : 经度
//CLLocationDegrees: double值
//方法
//distanceFromLocation
}
@end
iOS9新特性: 临时获取后台定位
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
/**
Xcode5开始,导入系统框架一般来说,不再需要导入框架.会自动引入框架
但是,有可能会报错,如果报错了,再导入
*/
/**
模拟器bug:定位的时候,模拟器会有bug,导致无法正常获取位置
1. Xcode7以前, 只需要切换一次模拟器即可. Xcode7以后有肯能需要多次. Xcode4.5
2. 还需要确认位置信息: 40.06 116.39
3. iOS8以后需要授权并配置plist键值
*/
@interface ViewController ()<CLLocationManagerDelegate>
/**
位置管理器
*/
@property (nonatomic,strong)CLLocationManager *locationManager;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
//1. 创建一个CLLocationManager对象
self.locationManager = [CLLocationManagernew];
//2. 请求授权 --> iOS8以后需要授权并配置plist键值;NSLocationAlwaysUsageDescription:随便写
// 请求授权这个步骤是在iOS8以后才出现的.如果iOS7之前直接调用会崩溃.
//为了防止iOS7奔溃,需要做判断: 2种方式: 1.判断能否响应 2.判断系统版本
//if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { }
if ([self.locationManagerrespondsToSelector:@selector(requestWhenInUseAuthorization)]) {
// 当用户使用时授权 :当程序能看见的时候,正在运行的时候
[self.locationManagerrequestWhenInUseAuthorization];
// 永久授权 :当程序后台运行 /锁屏界面都可以获取定位信息
//[self.locationManager requestAlwaysAuthorization];
}
/**
iOS9新特性: 临时获取后台定位
当使用了使用期间授权时,可以在需要后台定位的地方,添加allowsBackgroundLocationUpdates属性,并设置为YES.同时还需要打开后台定位模式 -->点击项目-->Capabilitys-->Background Modes-->勾选Location update
不用设置永久定位,此时就可以进行临时获取后台定位信息,但是屏幕上会有蓝条信息显示
*/
if ([UIDevicecurrentDevice].systemVersion.floatValue >=9.0) {
//allowsBackgroundLocationUpdates : 允许后台位置更新
self.locationManager.allowsBackgroundLocationUpdates = YES;
}
//3. 设置代理-->来获取用户定位的数据
self.locationManager.delegate =self;
//4. 开始定位
[self.locationManagerstartUpdatingLocation];
}
#pragma mark 定位的代理方法
/**
当完成位置更新的时候调用
locations: 位置信息数据
此方法会频繁调用.非常耗电
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
//locations : 包含了经纬度, 速度等信息
NSLog(@"locations: %@", locations);
}
@end
地理编码:把地名转换成经纬度,可能会出现一对多的情况;
#import "GeocoderViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface GeocoderViewController ()
@property (weak, nonatomic) IBOutletUITextField *addressTF;
/**
纬度
*/
@property (weak, nonatomic) IBOutletUILabel *latitudeLabel;
/**
经度
*/
@property (weak, nonatomic) IBOutletUILabel *longitudeLabel;
@property (weak, nonatomic) IBOutletUILabel *detailAddressLabel;
@end
@implementation GeocoderViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)geocoderClick:(id)sender {
//1. 创建CLGeocoder对象
CLGeocoder *geocoder = [CLGeocodernew];
//2. 调用地理编码方法
//placemarks: 地标对象
//CLPlacemark中有CLLocation(可以获得经纬度),region,街道名称,城市,州很多信息。
[geocoder geocodeAddressString:self.addressTF.textcompletionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks, NSError * _Nullable error) {
//3.1 防错处理
if (placemarks.count ==0 || error) {
NSLog(@"解析出错");
return;
}
//3.2 解析数据
// 正地理编码,一个地名可能对应多个经纬度.所以,实际做的时候应该给用户一个列表选择
// 咱们这里不做处理了
for (CLPlacemark *placemarkin placemarks) {
//3.3 经纬度
self.latitudeLabel.text = [NSStringstringWithFormat:@"%f",placemark.location.coordinate.latitude];
self.longitudeLabel.text = [NSStringstringWithFormat:@"%f",placemark.location.coordinate.longitude];
NSLog(@"la: %f, long: %f", placemark.location.coordinate.latitude
, placemark.location.coordinate.longitude);
//3.4 详细地址 --name
self.detailAddressLabel.text = placemark.name;
//NSLog(@"name: %@", placemark.name);
NSLog(@"city: %@",placemark.locality);
// 取城市的时候,locality有可能为空.为了避免取城市的时候程序崩溃,可以使用administrativeArea暂时代替一下
NSLog(@"administrativeArea%@",placemark.administrativeArea);
}
}];
}
@end
#import "ReverceGeocoderViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ReverceGeocoderViewController ()
@property (weak, nonatomic) IBOutletUITextField *latitudeTF;
@property (weak, nonatomic) IBOutletUITextField *longitudeTF;
@property (weak, nonatomic) IBOutletUILabel *cityLabel;
@end
@implementation ReverceGeocoderViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)reverceGeocoderClick:(id)sender {
//1. 创建Geocoder对象
CLGeocoder *geocoder = [CLGeocodernew];
//2.1 创建位置对象
CLLocation *location = [[CLLocationalloc]initWithLatitude:[self.latitudeTF.textdoubleValue]longitude:[self.longitudeTF.textdoubleValue]];
//2.2 调用反地理编码方法
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks,NSError *_Nullable error) {
//3.1 防错处理
if (placemarks.count ==0 || error) {
return;
}
//3.2 解析数据反地理编码,只会对应一个唯一的地址,所以不需要for循环
CLPlacemark *placemark = placemarks.lastObject;
//locality: 城市
if (placemark.locality) {
self.cityLabel.text = placemark.locality;
} else {
//administrativeArea: 行政区域
self.cityLabel.text = placemark.administrativeArea;
}
}];
}
@end
/**
需求:
1. 显示用户位置
2. 点击大头针,显示详情信息 -->反地理编码
3. 切换地图类型
4. 返回用户当前位置
5. 放大和缩小(了解)
*/
#import "ViewController.h"
#import <MapKit/MapKit.h>
// MapKit包含了CoreLotion框架
// 如果使用了SB或者Xib导入MapView的时候,需要导入框架
// MapView本身就有属性可以实现跟踪用户位置
@interface ViewController ()<MKMapViewDelegate>
@property (nonatomic,strong)CLLocationManager *mgr;
/**
地图属性
*/
@property (weak, nonatomic) IBOutletMKMapView *mapView;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
//1. 创建位置管理器并授权
self.mgr = [CLLocationManagernew];
// 请求授权 --> 配置plist
if ([self.mgrrespondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[self.mgrrequestWhenInUseAuthorization];
}
//2. 显示用户位置
//Tracking: 跟踪
//userTrackingMode: 用户跟踪模式
/**
MKUserTrackingModeNone = 0, // the user's location is not followed
MKUserTrackingModeFollow, // the map follows the user's location
MKUserTrackingModeFollowWithHeading, // the map follows the user's location and heading
*/
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
//3. 设置代理 --> 获取用户位置
self.mapView.delegate =self;
/**
iOS9新特性 -显示交通状况 /显示比例尺 / 显示指南针
*/
//1.显示交通状况
self.mapView.showsTraffic =YES;
//2.显示比例尺
self.mapView.showsScale =YES;
//3.显示指南针 (默认YES)
self.mapView.showsCompass =NO;
}
#pragma mark - MapView代理方法
/**
当完成用户位置更新的时候回调用
userLocation: 显示用户位置的大头针模型(MKUserLocation是系统大头针模型)
*/
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
//1. 获取经纬度
NSLog(@"la: %f, long: %f",userLocation.location.coordinate.latitude, userLocation.location.coordinate.longitude );
//2. 设置标题子标题
// userLocation.title = @"北京市";
// userLocation.subtitle = @"asasflsdafsa";
//2.1 创建Geocoder对象
CLGeocoder *geocoder = [CLGeocodernew];
//2.2 调用反地理编码方法 -->头文件第一个方法
[geocoder reverseGeocodeLocation:userLocation.locationcompletionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks, NSError * _Nullable error) {
//2.3 解析数据
if (placemarks.count ==0 || error) {
return;
}
CLPlacemark *placemark = placemarks.firstObject;
//locality: 城市
if (placemark.locality) {
userLocation.title = placemark.locality;
} else {
//administrativeArea: 行政区域,吧行政区域付给大头针模型的title
userLocation.title = placemark.administrativeArea;
}
//name: 详细地址
userLocation.subtitle = placemark.name;
}];
}
/**
地图显示区域发生改变时调用
*/
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
//1. 获取当前显示大小的跨度
NSLog(@"latitudeDelta: %f,longitudeDelta: %f", mapView.region.span.latitudeDelta, mapView.region.span.longitudeDelta);
// 放大地图:将显示跨度缩小一倍即可
// 放大地图:将显示跨度放大一倍即可
// 在按钮点击的时候,先获取当前显示跨度大小,然后按照需求放大或缩小跨度,最后再次调用setRegion方法
// latitudeDelta: 0.046142,longitudeDelta: 0.034943首次运行完毕:
// latitudeDelta: 0.021251,longitudeDelta: 0.016093
// latitudeDelta: 0.010625,longitudeDelta: 0.008047
}
#pragma mark - 其他方法
#pragma mark 切换地图类型
- (IBAction)changeMapTypeClick:(UISegmentedControl *)sender {
/**
MKMapTypeStandard = 0, 普通
MKMapTypeSatellite, 卫星
MKMapTypeHybrid, 混合
下面2个属性是iOS9新增的类型,但是中国区无用
MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0),
MKMapTypeHybridFlyover NS_ENUM_AVAILABLE(10_11, 9_0),
一般不会使用卫星这种类型,没什么用
*/
switch (sender.selectedSegmentIndex) {
case 0:
self.mapView.mapType =MKMapTypeStandard;
break;
case 1:
self.mapView.mapType =MKMapTypeSatellite;
break;
case 2:
self.mapView.mapType =MKMapTypeHybrid;
break;
default:
break;
}
}
#pragma mark 返回用户的位置
- (IBAction)backUserLocationClick:(id)sender {
// 设置地图的中心点经纬度 -->没有动画
//self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;
// 设置地图的中心点经纬度 -->有动画
//[self.mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate animated:YES];
// 设置地图的中心点经纬度并且改变地图的显示跨度
//1. 中心点坐标.
CLLocationCoordinate2D centerCoordinate =self.mapView.userLocation.location.coordinate;
//2. 显示跨度大小 1°约等于111KM
MKCoordinateSpan span =MKCoordinateSpanMake(0.01,0.01);
//3. 设置Region属性 -->没有动画
//self.mapView.region = MKCoordinateRegionMake(centerCoordinate, span);
// 调用set方法来增加动画
[self.mapView setRegion:MKCoordinateRegionMake(centerCoordinate, span)animated:YES];
}
#pragma mark 放大地图
//在按钮点击的时候,先获取当前显示跨度大小,然后按照需求放大或缩小跨度,最后再次调用setRegion方法
- (IBAction)zoomInClick:(id)sender {
//1. 将当前的显示跨度缩小一倍
//region : 是当前地图显示的区域
CGFloat latitude =self.mapView.region.span.latitudeDelta * 0.5;
CGFloat longitude =self.mapView.region.span.longitudeDelta * 0.5;
//2. 设置 region
// 设置范围, 带动画
[self.mapView setRegion:MKCoordinateRegionMake(self.mapView.region.center,MKCoordinateSpanMake(latitude, longitude)) animated:YES];
}
#pragma mark 缩小地图
- (IBAction)zoomOutClick:(id)sender {
//1. 将当前的显示跨度放大一倍
//region : 是当前地图显示的区域
CGFloat latitude =self.mapView.region.span.latitudeDelta * 2;
CGFloat longitude =self.mapView.region.span.longitudeDelta * 2;
// 经纬度: 经360纬180
// 苹果地图能显示的最大跨度147左右
if (latitude > 140 || longitude > 140) {
return;
}
//2. 设置 // 设置范围,带动画
[self.mapView setRegion:MKCoordinateRegionMake(self.mapView.region.center,MKCoordinateSpanMake(latitude, longitude)) animated:YES];
}
@end
添加大头针
#import <Foundation/Foundation.h>
//1. 导入框架
#import <MapKit/MapKit.h>
//2. 遵守协议
@interface MyAnnotation :NSObject<MKAnnotation>
//3. 拷贝协议中的属性(需要删除readonly属性)
@property (nonatomic)CLLocationCoordinate2D coordinate;
@property (nonatomic,copy,nullable)NSString *title;
@property (nonatomic,copy,nullable)NSString *subtitle;
@end
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import "MyAnnotation.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutletMKMapView *mapView;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// 自定义大头针模型:需要自定义大头针模型
MyAnnotation *annotation1 = [MyAnnotationnew];
annotation1.coordinate =CLLocationCoordinate2DMake(40 ,116);
annotation1.title = @"北京市";
annotation1.subtitle = @"北京市是一个迷人的城市";
//Annotation: 标注/注解 大头针
[self.mapViewaddAnnotation:annotation1];
MyAnnotation *annotation2 = [MyAnnotationnew];
annotation2.coordinate =CLLocationCoordinate2DMake(23 ,113);
annotation2.title = @"广州市";
annotation2.subtitle = @"广州市是一个令人向往的城市";
//Annotation: 标注/注解 大头针
[self.mapView addAnnotation:annotation2];
}
#pragma mark 点击地图上的位置添加大头针
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//1. 获取点击的点
CGPoint point = [[touches anyObject] locationInView:self.mapView];
//2. 将点转换成经纬度
CLLocationCoordinate2D coordinate = [self.mapView convertPoint:pointtoCoordinateFromView:self.mapView];
//3. 添加大头针模型
MyAnnotation *annotation = [MyAnnotationnew];
annotation.coordinate = coordinate;
//可以使用反地理编码获取title和subtitle
annotation.title = @"广州市";
annotation.subtitle = @"广州市是一个令人向往的城市";
[self.mapViewaddAnnotation:annotation];
}
@end
添加自定义大头针
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import "MyAnnotation.h"
@interface ViewController ()<MKMapViewDelegate>
@property (weak, nonatomic) IBOutletMKMapView *mapView;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// 1. 设置地图的代理方法
self.mapView.delegate =self;
// 自定义大头针模型:需要自定义大头针模型
MyAnnotation *annotation1 = [MyAnnotationnew];
annotation1.coordinate =CLLocationCoordinate2DMake(40 ,116);
annotation1.title = @"北京市";
annotation1.subtitle = @"北京市是一个迷人的城市";
//Annotation: 标注/注解 大头针
[self.mapViewaddAnnotation:annotation1];
MyAnnotation *annotation2 = [MyAnnotationnew];
annotation2.coordinate =CLLocationCoordinate2DMake(23 ,113);
annotation2.title = @"广州市";
annotation2.subtitle = @"广州市是一个令人向往的城市";
//Annotation: 标注/注解 大头针
[self.mapViewaddAnnotation:annotation2];
}
#pragma mark 地图的代理方法
/**
当添加大头针模型的时候,会调用此方发设置大头针View
*/
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// 如果返回nil,代表着用户没有自定义大头针的需求.所有的大头针显示由系统控制
//MKUserLocation --> 系统显示用户位置的大头针类
// 如果不是自己的大头针模型类,返回nil
if (![annotation isKindOfClass:[MyAnnotation class]]) {
return nil;
}
static NSString *ID =@"annoView";
//MKAnnotationView: 里面有一个image属性,默认没有值,需要设置一张图
//MKPinAnnotationView: 默认有图像
//如果要更改颜色,设置掉落效果只能找子类 MKPinAnnotationView
MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];
if (annoView == nil) {
annoView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID];
//如果大头针自定义了,标题和子标题默认不会实现;
//设置大头针可以点击,显示标题和子标题
annoView.canShowCallout=YES;
//设置大头针左右附属视图
annoView.leftCalloutAccessoryView=[[UISwitchalloc]init];
annoView.rightCalloutAccessoryView=[[UISwitchalloc]init];
//设置大头针头像
// annoView.image=[UIImageimageNamed:@"one"];
//1. 更改颜色
/**
pinColor: iOS9以前的属性,只能有3种颜色
MKPinAnnotationColorRed = 0,
MKPinAnnotationColorGreen,
MKPinAnnotationColorPurple
*/
annoView.pinTintColor = [UIColor colorWithRed:arc4random_uniform(256) /255.0 green:arc4random_uniform(256) /255.0blue:arc4random_uniform(256) /255.0alpha:1];
//2. 动画掉落
annoView.animatesDrop = YES;
}
return annoView;
}
//-(void)setAnnotation:(id<MKAnotation>)annotation{
//大头针自定义view和cell一样,唯一不同的是,大头针不用赋值模型数据;
//原因是大头针的view会自动调用setAnnotation方法(模型的set方法);
//系统会自己赋值模型数据;一旦重写,方法就会丢弃,会造成程序崩溃;如果重写,又不希望程序崩溃,要调用父类的方法;[super setAnnotation:annotation];
}
#pragma mark 点击地图上的位置添加大头针
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//1. 获取点击的点
CGPoint point = [[touches anyObject] locationInView:self.mapView];
//2. 将点转换成经纬度
CLLocationCoordinate2D coordinate = [self.mapViewconvertPoint:pointtoCoordinateFromView:self.mapView];
//3. 添加大头针模型
MyAnnotation *annotation = [MyAnnotationnew];
annotation.coordinate = coordinate;
//可以使用反地理编码获取title和subtitle
annotation.title = @"广州市";
annotation.subtitle = @"广州市是一个令人向往的城市";
[self.mapView addAnnotation:annotation];
}
@end
地图导航
#import "ViewController.h"
#import <MapKit/MapKit.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutletUITextField *destinationTF;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)navigateClick:(id)sender {
//1. 创建CLGeocoder对象
CLGeocoder *geocoder = [CLGeocodernew];
//2. 调用地理编码方法
[geocoder geocodeAddressString:self.destinationTF.textcompletionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks, NSError * _Nullable error) {
//3. 解析数据
//3.1 防错处理
if (placemarks.count ==0 || error) {
return;
}
//3.2 获取CLPlacemar对象 -->地理编码
// 正向会有多个结果,咱们暂时取出一个
CLPlacemark *pm = placemarks.lastObject;
//3.3 创建一个MKPlacemark对象
MKPlacemark *mkpm = [[MKPlacemarkalloc]initWithPlacemark:pm];
//3.4 终点位置
MKMapItem *destinationItem = [[MKMapItemalloc]initWithPlacemark:mkpm];
//3.5 当前位置
MKMapItem *sourceItem = [MKMapItemmapItemForCurrentLocation];
//实现导航关键点:在于一个MKMapItem的open方法
//MKMapItem: 地图上的点
//需要起点和终点
//3.6 调用系统地图进行导航
NSArray *maptems = @[sourceItem, destinationItem];
// 导航模式. 地图类型.交通状态
NSDictionary *options =@{MKLaunchOptionsDirectionsModeKey :MKLaunchOptionsDirectionsModeTransit,MKLaunchOptionsMapTypeKey :@(MKMapTypeHybrid)};
[MKMapItem openMapsWithItems:maptemslaunchOptions:options];
}];
/**
MKMapTypeStandard = 0,
MKMapTypeSatellite,
MKMapTypeHybrid,
*/
}
@end
添加地图导航划线
#import "ViewController.h"
#import <MapKit/MapKit.h>
@interface ViewController ()<MKMapViewDelegate>
@property (weak,nonatomic)IBOutlet UITextField *destinationTF;//输入目的地
@property (weak, nonatomic) IBOutletMKMapView *mapView;
@property (nonatomic,strong)CLLocationManager *mgr;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
//请求授权 -->想要获取自己位置必须授权
self.mgr = [CLLocationManagernew];
if ([self.mgrrespondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[self.mgrrequestWhenInUseAuthorization];
}
//设置代理
self.mapView.delegate =self;
}
- (IBAction)navigateClick:(id)sender {
//1. 创建CLGeocoder对象
CLGeocoder *geocoder = [CLGeocodernew];
//2. 调用地理编码方法
[geocoder geocodeAddressString:self.destinationTF.textcompletionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks, NSError * _Nullable error) {
//3. 解析数据
//3.1 防错处理
if (placemarks.count ==0 || error) {
return;
}
//3.2 获取CLPlacemar对象 -->地理编码
// 正向会有多个结果,咱们暂时取出一个
CLPlacemark *pm = placemarks.lastObject;
//3.3 创建一个MKPlacemark对象
MKPlacemark *mkpm = [[MKPlacemarkalloc]initWithPlacemark:pm];
//3.4 终点位置
MKMapItem *destinationItem = [[MKMapItemalloc]initWithPlacemark:mkpm];
//3.5 当前位置
MKMapItem *sourceItem = [MKMapItemmapItemForCurrentLocation];
//3.6 计算路线
//1. 创建一个方向请求对象 --> 拼接URL地址的参数
MKDirectionsRequest *request = [MKDirectionsRequestnew];
request.source = sourceItem;
request.destination = destinationItem;
//2. 创建方向对象
MKDirections *directions = [[MKDirectionsalloc]initWithRequest:request];
//3. 调用方法计算路线
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *_Nullable response,NSError *_Nullable error) {
//3.1 防错处理
if (response.routes.count ==0 || error) {
return;
}
//3.2 获取路线信息polyline
for (MKRoute *routein response.routes) {
// 获取折线 多段线 polyline
MKPolyline *polyline = route.polyline;
//3.3 添加地图遮盖物
//Overlay: 遮盖物
[self.mapView addOverlay:polyline];
}
}];
}];
}
#pragma mark 还需要设置渲染物对象 --> MapView代理方法
/**
根据遮盖物来完成渲染
*/
//Renderer: 渲染
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
//1. 创建一个渲染物对象 MKPolylineRenderer-->MKOverlayRenderer子类
MKPolylineRenderer *polyline = [[MKPolylineRendereralloc]initWithOverlay:overlay];
//2. 设置线条颜色 --> 默认无色
polyline.strokeColor = [UIColorblueColor];
return polyline;
}
@end
=================================================================
百度地图集成
#import "AppDelegate.h"
#import <BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件
//#import <BaiduMapAPI_Map/BMKMapComponent.h>//引入地图功能所有的头文件
//
//#import <BaiduMapAPI_Search/BMKSearchComponent.h>//引入检索功能所有的头文件
//
//#import <BaiduMapAPI_Cloud/BMKCloudSearchComponent.h>//引入云检索功能所有的头文件
//
//#import <BaiduMapAPI_Location/BMKLocationComponent.h>//引入定位功能所有的头文件
//
//#import <BaiduMapAPI_Utils/BMKUtilsComponent.h>//引入计算工具所有的头文件
//
//#import <BaiduMapAPI_Radar/BMKRadarComponent.h>//引入周边雷达功能所有的头文件
//
//#import <BaiduMapAPI_Map/BMKMapView.h>//只引入所需的单个头文件
@interface AppDelegate ()
{
BMKMapManager* _mapManager;
}
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 要使用百度地图,请先启动BaiduMapManager
_mapManager = [[BMKMapManageralloc]init];
// 第三方SDK一般都在这里进行授权,也都需要填入授权KEY
// 鉴权未完成
// 如果要关注网络及授权验证事件,请设定 generalDelegate参数
BOOL ret = [_mapManagerstart:@"yzducGjmv9ydbpB0DBhiNiuU" generalDelegate:nil];
if (!ret) {
NSLog(@"manager start failed!");
}
return YES;
}
- (void)onGetNetworkState:(int)iError
{
if (0 == iError) {
NSLog(@"联网成功");
}
else{
NSLog(@"onGetNetworkState %d",iError);
}
}
- (void)onGetPermissionState:(int)iError
{
if (0 == iError) {
NSLog(@"授权成功");
}
else {
NSLog(@"onGetPermissionState %d",iError);
}
}
@end
--------
#import "ViewController.h"
#import <BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件
#import <BaiduMapAPI_Map/BMKMapComponent.h>//引入地图功能所有的头文件
#import <BaiduMapAPI_Search/BMKSearchComponent.h>//引入检索功能所有的头文件
#import <BaiduMapAPI_Cloud/BMKCloudSearchComponent.h>//引入云检索功能所有的头文件
#import <BaiduMapAPI_Location/BMKLocationComponent.h>//引入定位功能所有的头文件
#import <BaiduMapAPI_Utils/BMKUtilsComponent.h>//引入计算工具所有的头文件
#import <BaiduMapAPI_Radar/BMKRadarComponent.h>//引入周边雷达功能所有的头文件
#import <BaiduMapAPI_Map/BMKMapView.h>//只引入所需的单个头文件
@interface ViewController ()<BMKMapViewDelegate,BMKPoiSearchDelegate>
{
BMKMapView *_mapView;
BMKPoiSearch *_searcher;
}
@end
@implementation ViewController
/**
Bundle display name: 真正用于显示应用程序名称. 一般不用写, 默认会用Bundle Name.
国际化的时候才需要 -->微信
*/
- (void)viewDidLoad {
[superviewDidLoad];
_mapView = [[BMKMapViewalloc]init];
self.view =_mapView;
//addSubview必须设置frame
//self.view addSubview:<#(nonnull UIView *)#>
//1. 切换为卫星图
[_mapViewsetMapType:BMKMapTypeSatellite];
//2. 打开实时路况图层
[_mapViewsetTrafficEnabled:YES];
//3. 打开百度城市热力图图层(百度自有数据)
[_mapViewsetBaiduHeatMapEnabled:YES];
//4. 添加大头针
// 添加一个PointAnnotation
BMKPointAnnotation* annotation = [[BMKPointAnnotationalloc]init];
CLLocationCoordinate2D coor;
coor.latitude = 39.915;
coor.longitude = 116.404;
annotation.coordinate = coor;
annotation.title = @"这里是北京";
[_mapView addAnnotation:annotation];
//5. POI检索 -->将POI检索请求延迟发送即可
[selfperformSelector:@selector(poiSearch)withObject:nilafterDelay:2];
//6. 显示跨度 --> 地图层级
[_mapViewsetZoomLevel:16];
}
- (void)poiSearch
{
//初始化检索对象
_searcher =[[BMKPoiSearchalloc]init];
_searcher.delegate =self;
//发起检索
BMKNearbySearchOption *option = [[BMKNearbySearchOptionalloc]init];
///分页索引,可选,默认为0
option.pageIndex = 0;
///分页数量,可选,默认为10,最多为50
option.pageCapacity = 10;
// 经纬度
option.location =CLLocationCoordinate2DMake(39.915,116.404);
option.keyword = @"小吃";
BOOL flag = [_searcherpoiSearchNearBy:option];
if(flag)
{
NSLog(@"周边检索发送成功");
}
else
{
NSLog(@"周边检索发送失败");
}
}
//实现PoiSearchDeleage处理回调结果
- (void)onGetPoiResult:(BMKPoiSearch*)searcher result:(BMKPoiResult*)poiResultList errorCode:(BMKSearchErrorCode)error
{
// 一般来说,接受到POI搜索结果,显示大头针 / 提供列表
if (error ==BMK_SEARCH_NO_ERROR) {
//在此处理正常结果
for (BMKPoiInfo *poiInfoin poiResultList.poiInfoList) {
//添加大头针
BMKPointAnnotation* annotation = [[BMKPointAnnotationalloc]init];
annotation.coordinate = poiInfo.pt;
annotation.title = poiInfo.address;
[_mapView addAnnotation:annotation];
}
}
elseif (error ==BMK_SEARCH_AMBIGUOUS_KEYWORD){
//当在设置城市未找到结果,但在其他城市找到结果时,回调建议检索城市列表
// result.cityList;
NSLog(@"起始点有歧义");
} else {
NSLog(@"抱歉,未找到结果");
NSLog(@"error: %d",error);
}
}
- (void)viewWillAppear:(BOOL)animated
{
[_mapViewviewWillAppear];
_mapView.delegate =self;//此处记得不用的时候需要置nil,否则影响内存的释放
}
- (void)viewWillDisappear:(BOOL)animated
{
[_mapViewviewWillDisappear];
_mapView.delegate =nil;//不用时,置nil
_searcher.delegate =nil;//不使用时将delegate设置为 nil
}
@end