iOS之原生地图的使用详解

一.实现一次定位(实际上就是持续定为,完成定位更新的时候停止定位,就成了一次定位)

@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


==================================================================
mapView的使用


/**

 需求

 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. 显示跨度大小约等于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;

    

    // 经纬度: 360180

    // 苹果地图能显示的最大跨度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;

    

    //可以使用反地理编码获取titlesubtitle

    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;

    

    //可以使用反地理编码获取titlesubtitle

    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];

        

        //实现导航关键点:在于一个MKMapItemopen方法

        //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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值