iOS开发之高德地图

1.使用Apple自带的高德地图
2.通过地名定位转换出座标,通过座标定位出详细信息
3.定位,显示地图,地图添加大头针,自定义大头针

1.使用Apple自带的高德地图
1.)需引入两个头文件:
(1). CoreLocation/CoreLocation.h用于定位
(2). MapKit/MapKit.h用于显示地图

#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>

2)定义一个高德地图属性

@interface MapOfAppleViewController ()

@property (nonatomic, strong) CLGeocoder *geocoder;

@end

3)viewDidLoad方法

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.view.backgroundColor = [UIColor whiteColor];
    /**
     初始化高德地图
     */
    self.geocoder = [[CLGeocoder alloc]init];
    /* 下面会详述该方法 */
    //[self location];
    [self listPlacemark];
}

4)location方法(此方法只有定位,没有重定位)

- (void)location
{
    /**
     *  根据"XXX"进行地理编码
     *
     *  @param placemarks block
     *  @param error      nil
     *
     *  @return void
     */
[self.geocoder geocodeAddressString:@"沙河口区" completionHandler:^(NSArray *placemarks, NSError *error) {

    /**
     *  获取第一个地标
     */
    CLPlacemark *clPlacemark = [placemarks firstObject];

    /**
     定位地标转化为地图的地标
     */
    MKPlacemark *mkPlacemark = [[MKPlacemark alloc]initWithPlacemark:clPlacemark];

    NSDictionary *options = @{MKLaunchOptionsMapTypeKey:@(MKMapTypeStandard)};
    MKMapItem *mapItem = [[MKMapItem alloc]initWithPlacemark:mkPlacemark];

    [mapItem openInMapsWithLaunchOptions:options];
}];

}

5)listPlacemark方法(此方法可以同时定位两个位置)

- (void)listPlacemark
{
    /**
     *  根据"XXX"进行地理编码
     *
     *  @param placemarks block
     *  @param error      nil
     *
     *  @return void
     */
    [self.geocoder geocodeAddressString:@"北京市" completionHandler:^(NSArray *placemarks, NSError *error) {

        /**
         *  获取第一个地标
         */
        CLPlacemark *clPlacemark1 = [placemarks firstObject];

        /**
         定位地标转化为地图的地标
         */
        MKPlacemark *mkPlacemark1 = [[MKPlacemark alloc]initWithPlacemark:clPlacemark1];

        /**
         *  注意地理编码一次只能定位到一个位置,不能同时定位,所在放到第一个位置定位完成回调函数中再次定位
         *
         *  @param placemarks block
         *  @param error      nil
         *
         *  @return void
         */
        [self.geocoder geocodeAddressString:@"大连市沙河口区" completionHandler:^(NSArray *placemarks, NSError *error) {
            CLPlacemark *clPlacemark2 = [placemarks firstObject];
            MKPlacemark *mkPlacemark2 = [[MKPlacemark alloc]initWithPlacemark:clPlacemark2];
            NSDictionary *options = @{MKLaunchOptionsMapTypeKey:@(MKMapTypeStandard)};
            MKMapItem *mapItem1 = [[MKMapItem alloc]initWithPlacemark:mkPlacemark1];
            MKMapItem *mapItem2 = [[MKMapItem alloc]initWithPlacemark:mkPlacemark2];
            [MKMapItem openMapsWithItems:@[mapItem1, mapItem2] launchOptions:options];      
        }];
    }]; 
}

运行效果图
这里写图片描述

2.通过地名定位转换出座标,通过座标定位出详细信息
1)需要导入CoreLocation.framework框架

这里写图片描述

2)在工程中引入头文件

/**
 *  导入CoreLocation.framework框架, 用于定位使用
 *
 *  @param void
 *
 *  @return nil
 */
#import <CoreLocation/CoreLocation.h>

3)签协议,使用高德地图

@interface TwoLocationStylesViewController ()<CLLocationManagerDelegate>
/**
 *  签好协议,定义高德地图属性
 */
@property (nonatomic, strong)CLGeocoder *geocoder;
@end

4)以下是实现部分ViewDidLoad

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];

    /**
     初始化高德地图属性
     */
    self.geocoder = [[CLGeocoder alloc]init];

#pragma mark ** 地名->座标

    [self getCoordinateByAddress:@"大连"];
#pragma mark ** 座标->地名

    //[self getAddressByLatitude:39.54 longitude:116.28];/* 北京座标 */

}

5)根据地名确定地理座标(地名->座标)

#pragma mark - 根据地名确定地理座标(地名->座标)
- (void)getCoordinateByAddress:(NSString *)address
{
[self.geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {
    /**
     *  地理编码,取得第一个地标,一个地名可能搜出多个地址(placemark为数组)
     */
    CLPlacemark *placemark = [placemarks firstObject];
    /**
     *  位置
     */
    CLLocation *location = placemark.location;
    /**
     *  区域
     */
    CLRegion *region = placemark.region;
    /**
     *  详细的地址信息通过字典存储
     */
    NSDictionary *addressDic = placemark.addressDictionary;
    /**
     *  详细信息字典包含以下信息
     *
     */
//    NSString *name = placemark.name;/* 地名 */
//    NSString *thoroughfare = placemark.thoroughfare;/* 街道 */
//    NSString *subThoroughfare = placemark.subThoroughfare;/* 街道相关信息,例如门牌等 */
//    NSString *locality = placemark.locality;/* 城市 */
//    NSString *subLocality = placemark.subLocality;/* 城市相关信息,例如标志性建筑 */
//    NSString *administrativeArea = placemark.administrativeArea;/* 州 */
//    NSString *subAdministrativeArea = placemark.subAdministrativeArea;/* 其他行政区域信息 */
//    NSString *postalCode = placemark.postalCode;/* 邮编 */
//    NSString *ISOcountryCode = placemark.ISOcountryCode;/* 国家编码 */
//    NSString *country = placemark.country;/* 国家 */
//    NSString *inlandWater = placemark.inlandWater;/* 水源,湖泊 */
//    NSString *ocean = placemark.ocean;/* 海洋 */
//    NSArray *areasOfInterest = placemark.areasOfInterest;/* 关联或者利益相关的地标 */

    /**
     *  以下是简短的输出
     */
    NSLog(@"位置:%@", location);
    NSLog(@"区域:%@", region);
    NSLog(@"详细信息:%@", addressDic);
}];  
}

6)根据座标获取地名(座标->地名)

- (void)getAddressByLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude
{
    /**
     反地理编码
     */
    CLLocation *location = [[CLLocation alloc]initWithLatitude:latitude longitude:longitude];
    [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
        CLPlacemark *placemark = [placemarks firstObject];
        NSLog(@"详细信息:%@", placemark.addressDictionary);
    }];

}

3.定位,显示地图,地图添加大头针,自定义大头针(结合之前的定位(地名->座标)实现一次显示地图,并且定位,插入自定义的大头针,点击大头针显示具体的位置信息)

1)导入MapKit.framework与CoreLocation.framework框架
这里写图片描述
2)引入两个头文件

/**
 *  这两个包必须导入
 *
 *  @param void
 *
 *  @return
 */
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>

3).h文件定义一个属性接受传来的值(输入的地理位置)

@interface MapAndLocationViewController : UIViewController

/**
 *  输入的名字
 */
@property (nonatomic, retain) NSString *place;

@end

4).m文件属性以及协议使用

/**
 *  签个协议 MKMapViewDelegate
 */
@interface MapAndLocationViewController ()<MKMapViewDelegate,CLLocationManagerDelegate>

@property (nonatomic, retain)CLLocationManager *locationManager;
/**
 *  位置
 */
@property (nonatomic, retain)CLLocation *location;
@property (nonatomic, retain)MKMapView *mapView;
/**
 *  详细信息显示名字
 */
@property (nonatomic, retain)NSString *name;

/**
 *  签好协议,定义高德地图属性
 */
@property (nonatomic, strong)CLGeocoder *geocoder;


@end

5)ViewDidLoad方法

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];

    /**
     初始化高德地图属性
     */
    self.geocoder = [[CLGeocoder alloc]init];

#pragma mark ** 地名->座标

    [self getCoordinateByAddress:self.place];
}

6)根据地名确定地理座标(地名->座标)(上面已经给予详细解释)

- (void)getCoordinateByAddress:(NSString *)address
{
    [self.geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {
        /**
         *  地理编码,取得第一个地标,一个地名可能搜出多个地址(placemark为数组)
         */
        CLPlacemark *placemark = [placemarks firstObject];
        /**
         *  位置
         */
        //CLLocation *location = placemark.location;
        self.location = placemark.location;
        /**
         *  区域
         */
        CLRegion *region = placemark.region;
        /**
         *  详细的地址信息通过字典存储
         */
        NSDictionary *addressDic = placemark.addressDictionary;
        /**
         *  详细信息字典包含以下信息
         *
         */
        self.name = placemark.name;/* 地名 */
        //    NSString *thoroughfare = placemark.thoroughfare;/* 街道 */
        //    NSString *subThoroughfare = placemark.subThoroughfare;/* 街道相关信息,例如门牌等 */
        //    NSString *locality = placemark.locality;/* 城市 */
        //    NSString *subLocality = placemark.subLocality;/* 城市相关信息,例如标志性建筑 */
        //    NSString *administrativeArea = placemark.administrativeArea;/* 州 */
        //    NSString *subAdministrativeArea = placemark.subAdministrativeArea;/* 其他行政区域信息 */
        //    NSString *postalCode = placemark.postalCode;/* 邮编 */
        //    NSString *ISOcountryCode = placemark.ISOcountryCode;/* 国家编码 */
        //    NSString *country = placemark.country;/* 国家 */
        //    NSString *inlandWater = placemark.inlandWater;/* 水源,湖泊 */
        //    NSString *ocean = placemark.ocean;/* 海洋 */
        //    NSArray *areasOfInterest = placemark.areasOfInterest;/* 关联或者利益相关的地标 */

        /**
         *  以下是简短的输出
         */
        NSLog(@"位置:%@", self.location);
        NSLog(@"区域:%@", region);
        NSLog(@"详细信息:%@", addressDic);
        /* 添加地图 */
        [self initMap];
    }];

}

7)添加地图控件

- (void)initMap
{
    /**
     *  地图大小
     */
    CGRect rect = [UIScreen mainScreen].bounds;
    self.mapView = [[MKMapView alloc]initWithFrame:rect];
    [self.view addSubview:self.mapView];

    /**
     *  签代理
     */
    self.mapView.delegate = self;

    /**
     请求定位服务
     */
    self.locationManager = [[CLLocationManager alloc]init];
    if (![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse) {
        [self.locationManager requestWhenInUseAuthorization];
    }

    /**
     *  用户位置追踪(标记用户当前位置,此时会调用定位服务)
     */
    self.mapView.userTrackingMode = MKUserTrackingModeFollow;

    /**
     *  地图类型
     */
    self.mapView.mapType = MKMapTypeStandard;

    /* 添加大头针 */
    [self addAnnotation];
}

8)添加大头针

- (void)addAnnotation
{

    /* 座标 */
    CLLocationCoordinate2D location1 = self.location.coordinate;
    KCAnnotation *annotation1 = [[KCAnnotation alloc]init];
    //以下两行使用的是系统弹出的大头针会显示出来 具体信息根据需求提供
    //annotation1.title = @"";
    //annotation1.subtitle = @"";
    annotation1.coordinate = location1;
    annotation1.image = [UIImage imageNamed:@"icon_paopao_waterdrop_streetscape.png"];
    annotation1.icon = [UIImage imageNamed:@"icon_mark1.png"];
    annotation1.detail = self.name;
    annotation1.rate = [UIImage imageNamed:@"icon_Movie_Star_rating.png"];
    [self.mapView addAnnotation:annotation1];

    /**
     *  定位北京
     *
     *  @param 39.87  北京经度
     *  @param 116.35 北京纬度
     *
     *  @return
     */
    CLLocationCoordinate2D location2=CLLocationCoordinate2DMake(39.87, 116.35);
    KCAnnotation *annotation2=[[KCAnnotation alloc]init];
    annotation2.coordinate=location2;
    annotation2.image=[UIImage imageNamed:@"icon_pin_floating.png"];
    annotation2.icon=[UIImage imageNamed:@"icon_mark1.png"];
    annotation2.detail=@"  中国.北京   ";
    annotation2.rate=[UIImage imageNamed:@"icon_Movie_Star_rating.png"];
    [_mapView addAnnotation:annotation2];
}

9)地图控件代理方法,显示大头针的时候会调用该方法,MKAnnotationView返回值是自定义的大头针对象

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    /**
     *  地图控件代理方法
     *
     *  @return 返回值是nil 返回的是系统默认的大头针 要使用自定义的大头针要加判断
     */
    if ([annotation isKindOfClass:[KCAnnotation class]]) {
        /* 定义一个缓冲池 */
        static NSString *reuse = @"AnnotationKey";
        MKAnnotationView *annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:reuse];
        if (!annotationView) {
            annotationView = [[MKAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:reuse];
            annotationView.calloutOffset = CGPointMake(0, 1);
            annotationView.leftCalloutAccessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"icon_classify_cafe"]];
        }
        /* 重新修改大头针,从缓冲池中取出来的大头针可能还会放到原来的位置(进池之前的位置) */
        annotationView.annotation = annotation;
        annotationView.image = ((KCAnnotation *)annotation).image;/* 重设大头针图片 */

        return annotationView;
    }
    else
        if ([annotation isKindOfClass:[KCCalloutAnnotation class]]) {
            /**
             *  作为自定义的弹出大头针 没有任何交互功能(canShowCallout = false, 这是默认值),可以添加其他的视图(继承自UIView)
             *
             *  @return
             */

            KCCalloutAnnotationView *calloutView = [KCCalloutAnnotationView calloutViewWithMapView:mapView];
            calloutView.annotation = annotation;
            return calloutView;
        }
    else
    {
        return nil;
    }

}

10)选中大头针触发的方法(弹出详情视图大头针)

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    KCAnnotation *annotation = view.annotation;
    if ([view.annotation isKindOfClass:[KCAnnotation class]]) {
        /* 添加一个详情视图大头针 */
        KCCalloutAnnotation *annotation1 = [[KCCalloutAnnotation alloc]init];
        annotation1.icon = annotation.icon;
        annotation1.detail = annotation.detail;
        annotation1.rate = annotation.rate;
        annotation1.coordinate = annotation.coordinate;

        [mapView addAnnotation:annotation1];
    }
}

11)取消选中时触发

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
    [self removeCustomAnnotation];
}

12)移除所有自定义的大头针

- (void)removeCustomAnnotation
{
[self.mapView.annotations enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isKindOfClass:[KCCalloutAnnotation class]]) {
        [self.mapView removeAnnotation:obj];
    }
}];
}

1.自定义的大头针KCAnnotation

1)引入头文件

#import <MapKit/MapKit.h>

2)需要的属性说明(title,subtitle这两个属性可根据需要保留或者去掉)

/**
 *  定义一个model
 */
@interface KCAnnotation : NSObject<MKAnnotation>

@property (nonatomic)CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

/* 创建大头针视图的时候使用 */
@property (nonatomic, strong) UIImage *image;
/* 大头针详情左侧图标 */
@property (nonatomic, strong) UIImage *icon;
/* 大头针详情描述 */
@property (nonatomic, strong) NSString *detail;
/* 大头针右下方星级评价 */
@property (nonatomic, strong) UIImage *rate;

@end

2.自定义弹出的大头针KCCalloutAnnotation

1)引入头文件

#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>

2)属性和协议的使用

@interface KCCalloutAnnotation : NSObject<MKAnnotation>

@property (nonatomic)CLLocationCoordinate2D coordinate;

/* 设置为只读readonly 弹出的大头针不具备其他作用 */
@property (nonatomic, copy, readonly) NSString *title;
@property (nonatomic, copy, readonly) NSString *subtitle;

/* 左侧图标 */
@property (nonatomic, strong) UIImage *icon;
/* 详情描述 */
@property (nonatomic, copy) NSString *detail;
/* 星级评价 */
@property (nonatomic, strong) UIImage *rate;


@end

3.弹出大头针的自适应(模型:根据系统大头针信息生成自定义大头针)KCCalloutAnnotationView
1)导入头文件

#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "KCCalloutAnnotation.h"

2)属性以及便利构造器(此处会有一个警告,不过不影响,可以忽略)

@interface KCCalloutAnnotationView : MKAnnotationView

@property (nonatomic, strong) KCCalloutAnnotation *annotation;
//便利构造器
+ (instancetype)calloutViewWithMapView:(MKMapView *)mapView;

@end

3)宏定义

#define kSpacing 5
#define kDetailFontSize 12
#define kViewOfset 80

4)大头针的属性

/**
 *  自定义弹出的大头针
 */
@interface KCCalloutAnnotationView ()

@property (nonatomic, retain) UIView *backgroundView;
@property (nonatomic, retain) UIImageView *iconView;
@property (nonatomic, retain) UILabel *detailLabel;
@property (nonatomic, retain) UIImageView *rateView;

@end

5)两个初始化方法

/**
 *  直接初始化,没有大小
 *
 *  @return 返回一个大头针
 */
- (instancetype)init
{
    if (self = [super init]) {
        [self layoutUI];
    }
    return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self layoutUI];
    }
    return self;
}

6)UI布局

- (void)layoutUI
{
    /* 背景 */
    self.backgroundView = [[UIView alloc]init];
    self.backgroundView.backgroundColor = [UIColor whiteColor];

    /* 左侧图标 */
    self.iconView = [[UIImageView alloc]init];

    /* 详情 */
    self.detailLabel = [[UILabel alloc]init];
    self.detailLabel.lineBreakMode = NSLineBreakByCharWrapping;
    self.detailLabel.font = [UIFont systemFontOfSize:kDetailFontSize];

    /* 星级 */
    self.rateView = [[UIImageView alloc]init];

    [self addSubview:self.backgroundView];
    [self addSubview:self.iconView];
    [self addSubview:self.detailLabel];
    [self addSubview:self.rateView];
}

7)便利构造器

/**
 *  便利构造器 初始化
 *
 *  @param mapView
 *
 *  @return 自定义弹出的大头针
 */
+ (instancetype)calloutViewWithMapView:(MKMapView *)mapView
{
static NSString *calloutkey = @"calloutKey";
    KCCalloutAnnotationView *calloutView = (KCCalloutAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:calloutkey];
    if (!calloutView) {
        calloutView = [[KCCalloutAnnotationView alloc]init];
    }
    return calloutView;
}

8)设置大头针模型(视图内容)


- (void)setAnnotation:(KCCalloutAnnotation *)annotation
{
    [super setAnnotation:annotation];
    /* 根据模型调整布局 */
    _iconView.image = annotation.icon;
    _iconView.frame = CGRectMake(kSpacing, kSpacing, annotation.icon.size.width, annotation.icon.size.height);

    _detailLabel.text = annotation.detail;
    float detailWidth = 150.0;
    CGSize detailSize = [annotation.detail boundingRectWithSize:CGSizeMake(detailWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:kDetailFontSize]} context:nil].size;
    float detailX = CGRectGetMaxX(_iconView.frame) + kSpacing;
    _detailLabel.frame = CGRectMake(detailX, kSpacing, detailSize.width, detailSize.height);

    _rateView.image = annotation.rate;
    _rateView.frame = CGRectMake(detailX, CGRectGetMaxY(_detailLabel.frame)+kSpacing, annotation.rate.size.width, annotation.rate.size.height);

    float backgroundWidth = CGRectGetMaxX(_detailLabel.frame)+kSpacing;
    float backgroundHeight = _iconView.frame.size.height + 2 * kSpacing;
    _backgroundView.frame = CGRectMake(0, 0, backgroundWidth, backgroundHeight);
    self.bounds = CGRectMake(0, 0, backgroundWidth, backgroundHeight+kViewOfset);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章