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);
}