iOS百度地图使用

@implementation HMAnnotationView


- (instancetype)initWithAnnotation:(id)annotation reuseIdentifier:(NSString *)reuseIdentifier


//自定义大头针方法
{
    if (self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {
        // 初始化
        // 设置大头针标题是否显示
        self.canShowCallout = YES;
        
        // 设置大头针左边的辅助视图
        self.leftCalloutAccessoryView = [[UISwitch alloc] init];
        
        // 设置大头针右边的辅助视图
        self.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
    }
    return self;
}


+ (instancetype)annotationViewWithMap:(MKMapView *)mapView
{
    static NSString *identifier = @"anno";
    
    // 1.从缓存池中取
    HMAnnotationView *annoView = (HMAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    // 2.如果缓存池中没有, 创建一个新的
    if (annoView == nil) {
        
        annoView = [[HMAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:identifier];
    }


    return annoView;
}


//- (void)setAnnotation:(id)annotation
- (void)setAnnotation:(HMAnnotation *)annotation
{
    [super setAnnotation:annotation];
    
//     处理自己特有的操作
    self.image = [UIImage imageNamed:annotation.icon];
    
}
@end


//大头针的属性


@interface HMAnnotation : NSObject
 /**
 *  大头针的位置
 */
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
/**
 *  大头针标题
 */
@property (nonatomic, copy) NSString *title;
/**
 *  大头针的子标题
 */
@property (nonatomic, copy) NSString *subtitle;


/**
 *  图标
 */
@property (nonatomic, copy) NSString *icon;
@end


@interface ViewController ()
/**
 *  地图
 */
@property (weak, nonatomic) IBOutlet MKMapView *customMapView;


@property (nonatomic, strong) CLLocationManager *mgr;
/**
 *  地理编码对象
 */
@property (nonatomic ,strong) CLGeocoder *geocoder;
- (IBAction)addAnno;
@end


@implementation ViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 注意:在iOS8中, 如果想要追踪用户的位置, 必须自己主动请求隐私权限
    if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
        // 主动请求权限
        self.mgr = [[CLLocationManager alloc] init];
        
        [self.mgr requestAlwaysAuthorization];
    }
    
    // 设置不允许地图旋转
    self.customMapView.rotateEnabled = NO;
    
    // 成为mapVIew的代理
    self.customMapView.delegate = self;
    
    // 如果想利用MapKit获取用户的位置, 可以追踪
    self.customMapView.userTrackingMode =  MKUserTrackingModeFollow;
    


}




#pragma MKMapViewDelegate
/**
 *  每次添加大头针就会调用(地图上有几个大头针就调用几次)
 *
 *  @param mapView    地图
 *  @param annotation 大头针模型
 *
 *  @return 大头针的view
 */
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation
{
//    NSLog(@"%s", __func__);
    NSLog(@"annotation === %@", annotation);
    // 对用户当前的位置的大头针特殊处理
    if ([annotation isKindOfClass:[HMAnnotation class]] == NO) {
        return nil;
    }
    
    // 注意: 如果返回nil, 系统会按照自己默认的方式显示
//    return nil;
    
    /*
    static NSString *identifier = @"anno";
    // 1.从缓存池中取
    // 注意: 默认情况下MKAnnotationView是无法显示的, 如果想自定义大头针可以使用MKAnnotationView的子类MKPinAnnotationView
    
    // 注意: 如果是自定义的大头针, 默认情况点击大头针之后是不会显示标题的, 需要我们自己手动设置显示
//    MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    
    
    MKAnnotationView *annoView = [mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    // 2.如果缓存池中没有, 创建一个新的
    if (annoView == nil) {
//        annoView = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:identifier];
        annoView = [[MKAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:identifier];
        
        // 设置大头针的颜色
//        annoView.pinColor = MKPinAnnotationColorPurple;
        
        // 设置大头针从天而降
//        annoView.animatesDrop = YES;
        
        // 设置大头针标题是否显示
        annoView.canShowCallout = YES;
        
        // 设置大头针标题显示的偏移位
//        annoView.calloutOffset = CGPointMake(-50, 0);
        
        // 设置大头针左边的辅助视图
        annoView.leftCalloutAccessoryView = [[UISwitch alloc] init];
        // 设置大头针右边的辅助视图
        annoView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
      
    }
    
    // 设置大头针的图片
    // 注意: 如果你是使用的MKPinAnnotationView创建的自定义大头针, 那么设置图片无效, 因为系统内部会做一些操作, 覆盖掉我们自己的设置
//    annoView.image = [UIImage imageNamed:@"category_4"];
    HMAnnotation *anno = (HMAnnotation *)annotation;
    annoView.image = [UIImage imageNamed:anno.icon];
    
    // 3.给大头针View设置数据
    annoView.annotation = annotation;
    
    // 4.返回大头针View
    return annoView;
     */
    
    // 1.创建大头针
    HMAnnotationView *annoView = [HMAnnotationView annotationViewWithMap:mapView];
    // 2.设置模型
    annoView.annotation = annotation;
    
    // 3.返回大头针
    return annoView;
}


/**
 *  每次更新到用户的位置就会调用(调用不频繁, 只有位置改变才会调用)
 *
 *  @param mapView      促发事件的控件
 *  @param userLocation 大头针模型
 */
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{


    // 利用反地理编码获取位置之后设置标题
    [self.geocoder reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray *placemarks, NSError *error) {
        CLPlacemark *placemark = [placemarks firstObject];
        NSLog(@"获取地理位置成功 name = %@ locality = %@", placemark.name, placemark.locality);
        userLocation.title = placemark.name;
        userLocation.subtitle = placemark.locality;
    }];
    
    /*
    // 设置地图显示的区域
    // 获取用户的位置
    CLLocationCoordinate2D center = userLocation.location.coordinate;
    // 指定经纬度的跨度
    MKCoordinateSpan span = MKCoordinateSpanMake(5 ,5);
    // 将用户当前的位置作为显示区域的中心点, 并且指定需要显示的跨度范围
    MKCoordinateRegion region = MKCoordinateRegionMake(center, span);
    
    // 设置显示区域
    [self.customMapView setRegion:region animated:YES];
     */
    
    [self.customMapView setCenterCoordinate:userLocation.location.coordinate animated:YES];
}
#pragma mark - 懒加载
- (CLGeocoder *)geocoder
{
    if (!_geocoder) {
        _geocoder = [[CLGeocoder alloc] init];
    }
    return _geocoder;
}


- (IBAction)addAnno {
    // 创建大头针模型
    HMAnnotation *anno = [[HMAnnotation alloc] init];
    anno.title = @"孙庄";
    anno.subtitle = @"育新小区";
    CGFloat latitude = 36.821199 + arc4random_uniform(20);
    CGFloat longitude = 116.858776 + arc4random_uniform(20);
    anno.coordinate = CLLocationCoordinate2DMake(latitude , longitude);
    anno.icon = @"category_1";
    
    // 添加大头针
    [self.customMapView addAnnotation:anno];
    
    
    // 创建大头针模型
    HMAnnotation *anno2 = [[HMAnnotation alloc] init];
    anno2.title = @"传智2";
    anno2.subtitle = @"育新小区2";
    CGFloat latitude2 = 36.821199 + arc4random_uniform(20);
    CGFloat longitude2 = 116.858776 + arc4random_uniform(20);
    anno2.coordinate = CLLocationCoordinate2DMake(latitude2 , longitude2);
    anno2.icon = @"category_2";
    
    // 添加大头针
    [self.customMapView addAnnotation:anno2];
}
@end


//系统自带的APP的导航
#import "ViewController.h"
#import


@interface ViewController ()


- (IBAction)startNavigation;
/**
 *  开始位置
 */
@property (weak, nonatomic) IBOutlet UITextField *startField;
/**
 *  结束位置
 */
@property (weak, nonatomic) IBOutlet UITextField *endField;
/**
 *  地理编码对象
 */
@property(nonatomic, strong) CLGeocoder *geocoder;
@end


@implementation ViewController




- (void)startNavigation
{
    // 1.获取用户输入的起点和终点
    NSString *startStr = self.startField.text;
    NSString *endStr = self.endField.text;
    if (startStr == nil || startStr.length == 0 ||
        endStr == nil || endStr.length == 0) {
        NSLog(@"请输入起点或者终点");
        return;
    }
    
    // 2.利用GEO对象进行地理编码获取到地标对象(CLPlacemark )
    // 2.1获取开始位置的地标
    [self.geocoder geocodeAddressString:startStr completionHandler:^(NSArray *placemarks, NSError *error) {
        if (placemarks.count == 0) return;
        
        // 开始位置的地标
        CLPlacemark *startCLPlacemark = [placemarks firstObject];
        
        
        // 3. 获取结束位置的地标
        [self.geocoder geocodeAddressString:endStr completionHandler:^(NSArray *placemarks, NSError *error) {
            
            if (placemarks.count == 0) return;
            
            // 结束位置的地标
            CLPlacemark *endCLPlacemark = [placemarks firstObject];
            
            // 开始导航
            [self startNavigationWithstartCLPlacemark:startCLPlacemark endCLPlacemark:endCLPlacemark];
        }];
        
    }];
}


/**
 *  开始导航
 *
 *  @param startCLPlacemark 起点的地标
 *  @param endCLPlacemark   终点的地标
 */
- (void)startNavigationWithstartCLPlacemark:(CLPlacemark *)startCLPlacemark endCLPlacemark:(CLPlacemark *)endCLPlacemark
{


    // 0.创建起点和终点
    // 0.1创建起点
    MKPlacemark *startPlacemark = [[MKPlacemark alloc] initWithPlacemark:startCLPlacemark];
    MKMapItem *startItem = [[MKMapItem alloc] initWithPlacemark:startPlacemark];;
    
    // 0.2创建终点
    MKPlacemark *endPlacemark = [[MKPlacemark alloc] initWithPlacemark:endCLPlacemark];
    MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endPlacemark];
    
    // 1. 设置起点和终点数组
    NSArray *items = @[startItem, endItem];
    
    
    // 2.设置启动附加参数
    NSMutableDictionary *md = [NSMutableDictionary dictionary];
    // 导航模式(驾车/走路)
    md[MKLaunchOptionsDirectionsModeKey] = MKLaunchOptionsDirectionsModeDriving;
    // 地图显示模式
//    md[MKLaunchOptionsMapTypeKey] = @(MKMapTypeHybrid);
    
    
    // 只要调用MKMapItem的open方法, 就可以打开系统自带的地图APP进行导航
    // Items: 告诉系统地图APP要从哪到哪
    // launchOptions: 启动系统自带地图APP的附加参数(导航的模式/是否需要先交通状况/地图的模式/..)
    [MKMapItem openMapsWithItems:items launchOptions:md];
}


#pragma mark - 懒加载
- (CLGeocoder *)geocoder
{
    if (!_geocoder) {
        self.geocoder = [[CLGeocoder alloc] init];
    }
    return _geocoder;
}
@end




//获取路线信息
@interface ViewController ()


- (IBAction)startNavigation;
/**
 *  开始位置
 */
@property (weak, nonatomic) IBOutlet UITextField *startField;
/**
 *  结束位置
 */
@property (weak, nonatomic) IBOutlet UITextField *endField;
/**
 *  地理编码对象
 */
@property(nonatomic, strong) CLGeocoder *geocoder;


@end


@implementation ViewController


/**
 *  点击开始导航按钮
 */
- (void)startNavigation
{
    // 1.获取用户输入的起点和终点
    NSString *startStr = self.startField.text;
    NSString *endStr = self.endField.text;
    if (startStr == nil || startStr.length == 0 ||
        endStr == nil || endStr.length == 0) {
        NSLog(@"请输入起点或者终点");
        return;
    }
    
    // 2.利用GEO对象进行地理编码获取到地标对象(CLPlacemark )
    // 2.1获取开始位置的地标
    [self.geocoder geocodeAddressString:startStr completionHandler:^(NSArray *placemarks, NSError *error) {
        if (placemarks.count == 0) return;
        
        // 开始位置的地标
        CLPlacemark *startCLPlacemark = [placemarks firstObject];
        
        
        // 3. 获取结束位置的地标
        [self.geocoder geocodeAddressString:endStr completionHandler:^(NSArray *placemarks, NSError *error) {
            
            if (placemarks.count == 0) return;
            
            // 结束位置的地标
            CLPlacemark *endCLPlacemark = [placemarks firstObject];
            
            // 开始导航
            [self startDirectionsWithstartCLPlacemark:startCLPlacemark endCLPlacemark:endCLPlacemark];
        }];
        
    }];
}


/**
 *  发送请求获取路线相信信息
 *
 *  @param startCLPlacemark 起点的地标
 *  @param endCLPlacemark   终点的地标
 */
- (void)startDirectionsWithstartCLPlacemark:(CLPlacemark *)startCLPlacemark endCLPlacemark:(CLPlacemark *)endCLPlacemark
{


    /*
     MKDirectionsRequest:说清楚:从哪里 --> 到哪里
     MKDirectionsResponse:从哪里 --> 到哪里 :的具体路线信息
     */
    
    // -1.创建起点和终点对象
    // -1.1创建起点对象
    MKPlacemark *startMKPlacemark = [[MKPlacemark alloc] initWithPlacemark:startCLPlacemark];
    MKMapItem *startItem = [[MKMapItem alloc] initWithPlacemark:startMKPlacemark];
    
    // -1.2创建终点对象
    MKPlacemark *endMKPlacemark = [[MKPlacemark alloc] initWithPlacemark:endCLPlacemark];
    MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endMKPlacemark];
    
    
    // 0.创建request对象
    MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
    // 0.1设置起点
    request.source = startItem;
    // 0.2设置终点
    request.destination = endItem;
    
    
    
    // 1.发送请求到苹果的服务器获取导航路线信息
    // 接收一个MKDirectionsRequest请求对象, 我们需要在该对象中说清楚:
    // 从哪里 --> 到哪里
    MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
    // 2.计算路线信息, 计算完成之后会调用blcok
    // 在block中会传入一个响应者对象(response), 这个响应者对象中就存放着路线信息
    [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
        
        
        // 打印获取到的路线信息
        // 2.1获取所有的路线
        NSArray *routes = response.routes;
        for (MKRoute *route in routes) {
            NSLog(@"%f千米 %f小时", route.distance / 1000, route.expectedTravelTime/ 3600);
            
            NSArray *steps = route.steps;
            for (MKRouteStep *step in steps) {
                NSLog(@"%@ %f", step.instructions, step.distance);
            }
            
        }
    }];
}


#pragma mark - 懒加载
- (CLGeocoder *)geocoder
{
    if (!_geocoder) {
        self.geocoder = [[CLGeocoder alloc] init];
    }
    return _geocoder;
}


@end




//路线的选择代码
#import "ViewController.h"
#import
#import "HMAnnotation.h"


@interface ViewController ()


@property (weak, nonatomic) IBOutlet MKMapView *mapVIew;


/**
 *  地理编码对象
 */
@property(nonatomic, strong) CLGeocoder *geocoder;


- (IBAction)drawLine;
@end


@implementation ViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
    self.mapVIew.delegate = self;
}


/**
 *  点击开始导航按钮
 */
- (IBAction)drawLine
{
    // 1.获取用户输入的起点和终点
    NSString *startStr = @"北京";
    NSString *endStr = @"云南";
    if (startStr == nil || startStr.length == 0 ||
        endStr == nil || endStr.length == 0) {
        NSLog(@"请输入起点或者终点");
        return;
    }
    
    // 2.利用GEO对象进行地理编码获取到地标对象(CLPlacemark )
    // 2.1获取开始位置的地标
    [self.geocoder geocodeAddressString:startStr completionHandler:^(NSArray *placemarks, NSError *error) {
        if (placemarks.count == 0) return;
        
        // 开始位置的地标
        CLPlacemark *startCLPlacemark = [placemarks firstObject];
        
        // 添加起点的大头针
        HMAnnotation *startAnno = [[HMAnnotation alloc ] init];
        startAnno.title = startCLPlacemark.locality;
        startAnno.subtitle = startCLPlacemark.name;
        startAnno.coordinate = startCLPlacemark.location.coordinate;
        [self.mapVIew addAnnotation:startAnno];
        
        // 3. 获取结束位置的地标
        [self.geocoder geocodeAddressString:endStr completionHandler:^(NSArray *placemarks, NSError *error) {
            
            if (placemarks.count == 0) return;
            
            // 结束位置的地标
            CLPlacemark *endCLPlacemark = [placemarks firstObject];
            
            // 添加终点的大头针
            HMAnnotation *endAnno = [[HMAnnotation alloc ] init];
            endAnno.title = endCLPlacemark.locality;
            endAnno.subtitle = endCLPlacemark.name;
            endAnno.coordinate = endCLPlacemark.location.coordinate;
            [self.mapVIew addAnnotation:endAnno];
            
            // 开始导航
            [self startDirectionsWithstartCLPlacemark:startCLPlacemark endCLPlacemark:endCLPlacemark];
        }];
        
    }];
}


/**
 *  发送请求获取路线相信信息
 *
 *  @param startCLPlacemark 起点的地标
 *  @param endCLPlacemark   终点的地标
 */
- (void)startDirectionsWithstartCLPlacemark:(CLPlacemark *)startCLPlacemark endCLPlacemark:(CLPlacemark *)endCLPlacemark
{


    /*
     MKDirectionsRequest:说清楚:从哪里 --> 到哪里
     MKDirectionsResponse:从哪里 --> 到哪里 :的具体路线信息
     */
    
    // -1.创建起点和终点对象
    // -1.1创建起点对象
    MKPlacemark *startMKPlacemark = [[MKPlacemark alloc] initWithPlacemark:startCLPlacemark];
    MKMapItem *startItem = [[MKMapItem alloc] initWithPlacemark:startMKPlacemark];
    
    // -1.2创建终点对象
    MKPlacemark *endMKPlacemark = [[MKPlacemark alloc] initWithPlacemark:endCLPlacemark];
    MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endMKPlacemark];
    
    
    // 0.创建request对象
    MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
    // 0.1设置起点
    request.source = startItem;
    // 0.2设置终点
    request.destination = endItem;
    
    
    
    // 1.发送请求到苹果的服务器获取导航路线信息
    // 接收一个MKDirectionsRequest请求对象, 我们需要在该对象中说清楚:
    // 从哪里 --> 到哪里
    MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
    // 2.计算路线信息, 计算完成之后会调用blcok
    // 在block中会传入一个响应者对象(response), 这个响应者对象中就存放着路线信息
    [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
        
        
        // 打印获取到的路线信息
        // 2.1获取所有的路线
        NSArray *routes = response.routes;
        for (MKRoute *route in routes) {
            NSLog(@"%f千米 %f小时", route.distance / 1000, route.expectedTravelTime/ 3600);
            
            //  3.绘制路线(本质: 往地图上添加遮盖)
            // 传递当前路线的几何遮盖给地图, 地图就会根据遮盖自动绘制路线
            // 当系统开始绘制路线时会调用代理方法询问当前路线的宽度/颜色等信息
            [self.mapVIew addOverlay:route.polyline];
            
            NSArray *steps = route.steps;
            for (MKRouteStep *step in steps) {
//                NSLog(@"%@ %f", step.instructions, step.distance);
            }
            
        }
    }];
}


#pragma mark - MKMapViewDelegate


// 过时
//- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay


// 绘制路线时就会调用(添加遮盖时就会调用)
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay
{
//    MKOverlayRenderer *renderer = [[MKOverlayRenderer alloc] init];
    // 创建一条路径遮盖
    NSLog(@"%s", __func__);
#warning 注意, 创建线条时候,一定要制定几何路线
    MKPolylineRenderer *line = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
    line.lineWidth = 5; // 路线的宽度
    line.strokeColor = [UIColor redColor];// 路线的颜色
    
    // 返回路线
    return line;
}


#pragma mark - 懒加载
- (CLGeocoder *)geocoder
{
    if (!_geocoder) {
        self.geocoder = [[CLGeocoder alloc] init];
    }
    return _geocoder;
}






@end


大头针的属性


#import
#import


@interface HMAnnotation : NSObject
 /**
 *  大头针的位置
 */
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
/**
 *  大头针标题
 */
@property (nonatomic, copy) NSString *title;
/**
 *  大头针的子标题
 */
@property (nonatomic, copy) NSString *subtitle;


/**
 *  图标
 */
@property (nonatomic, copy) NSString *icon;
@end















你可能感兴趣的:(iOS)