- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { static NSString *ID = @"anno"; MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID]; if (annoView == nil) { annoView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID]; // 顯示氣泡 annoView.canShowCallout = YES; // 設置綠色 annoView.pinColor = MKPinAnnotationColorGreen; } return annoView; }
#import "ViewController.h" #import <MapKit/MapKit.h> #import "MyAnnotation.h" @interface ViewController ()<MKMapViewDelegate> @property (weak, nonatomic) IBOutlet MKMapView *mapView; @property (weak, nonatomic) IBOutlet UITextField *latitude; @property (weak, nonatomic) IBOutlet UITextField *longitude; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //設置地圖的顯示風格 self.mapView.mapType = MKMapTypeStandard; //設置地圖可縮放 self.mapView.zoomEnabled = YES; //設置地圖可滾動 self.mapView.scrollEnabled = YES; //設置地圖可旋轉 self.mapView.rotateEnabled = YES; //設置顯示用戶顯示位置 self.mapView.showsUserLocation = YES; //爲MKMapView設置delegate self.mapView.delegate = self; // [self locateToLatitude:23.12672 longtitude:113.395]; NSLog(@"用戶當前是否位於地圖中:%d",self.mapView.userLocationVisible); } - (IBAction)goClicked:(UIButton *)sender { //關閉兩個文本框的虛擬鍵盤 // [self.latitude resignFirstResponder]; // [self.longitude resignFirstResponder]; //經度 NSString *latitudeStr = self.latitude.text; //緯度 NSString *longtitudeStr = self.longitude.text; //若是用戶輸入的經度、緯度爲空 if (latitudeStr != nil && latitudeStr.length > 0 && longtitudeStr!= nil && longtitudeStr.length > 0) { //設置經度、緯度 [self locateToLatitude:latitudeStr.floatValue longtitude:longtitudeStr.floatValue]; } } -(void)locateToLatitude:(CGFloat)latitude longtitude:(CGFloat)longitude { //設置地圖中的的經度、緯度 CLLocationCoordinate2D center = {latitude,longitude}; //也可使用以下方式設置經度、緯度 //center.latitude = latitude; //center.longitude = longitude; //設置地圖顯示的範圍 MKCoordinateSpan span; //地圖顯示範圍越小,細節越清楚; span.latitudeDelta = 0.01; span.longitudeDelta = 0.01; //建立MKCoordinateRegion對象,該對象表明地圖的顯示中心和顯示範圍 MKCoordinateRegion region = {center,span}; //設置當前地圖的顯示中心和顯示範圍 [self.mapView setRegion:region animated:YES]; UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)]; [self.mapView addGestureRecognizer:longPress]; } -(void)longPress:(UILongPressGestureRecognizer *)sender { CGPoint location = [sender locationInView:self.mapView]; //轉換經緯度 CLLocationCoordinate2D coordinate = [self.mapView convertPoint:location toCoordinateFromView:self.mapView]; // 建立標註 MyAnnotation *annotation = [[MyAnnotation alloc]init]; annotation.coordinate = coordinate; annotation.title = @"新的標註"; annotation.subtitle = @"開發..."; [self.mapView addAnnotation:annotation]; } #pragma mark - mapView代理方法 #pragma mark 顯示標註視圖 -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { static NSString *annotationID = @"annotation"; MKPinAnnotationView *view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationID]; if (!view) { view = [[MKPinAnnotationView alloc]init]; } view.annotation = annotation; // view.leftCalloutAccessoryView view.pinColor = MKPinAnnotationColorGreen; view.canShowCallout = YES; return view; } #pragma mark 代理方法 -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { CLLocationCoordinate2D coordinate = userLocation.location.coordinate; MKCoordinateSpan span = {0.001,0.001}; MKCoordinateRegion region = {coordinate,span}; //設置顯示區域 [self.mapView setRegion:region animated:YES]; MyAnnotation *annotation = [[MyAnnotation alloc]init]; annotation.coordinate = coordinate; annotation.title = @"中國"; annotation.subtitle = @"好牛B的地方"; //讓地圖顯示標註的區域 [self.mapView setCenterCoordinate:annotation.coordinate animated:YES]; } //當MKMapView顯示區域將要發生改變時激發該方法 -(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated { NSLog(@"地圖控件的顯示區域要發生改變"); } //當MKMapView顯示區域改變完成時激發該方法 -(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { NSLog(@"地圖控件完成了改變"); } //當地圖控件MKMapView開始加載數據時激發該方法 -(void)mapViewWillStartLoadingMap:(MKMapView *)mapView { NSLog(@"地圖控件開始加載地圖數據"); //建立MKCoordinateRegion對象,該對象表明地圖的顯示中心和顯示範圍 MKCoordinateRegion region = mapView.region; self.latitude.text = [NSString stringWithFormat:@"%f",region.center.latitude]; self.longitude.text = [NSString stringWithFormat:@"%f",region.center.longitude]; } //當MKMapView加載數據完成時激發該方法 -(void)mapViewDidFinishLoadingMap:(MKMapView *)mapView { NSLog(@"地圖控件加載地圖數據完成"); NSLog(@"%@",mapView); } //當MKMapView加載數據失敗時激發該方法 -(void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error { NSLog(@"地圖控件加載地圖數據發生錯誤:錯誤信息:%@",error); } //當MKMapView開始渲染地圖時激發該方法 -(void)mapViewWillStartRenderingMap:(MKMapView *)mapView { NSLog(@"地圖控件開始渲染地圖"); } //當MKMapView渲染地圖完成時激發該方法 -(void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered { NSLog(@"地圖控件渲染完成"); } @end
MyAnnotation.h文件內容git
#import <Foundation/Foundation.h> #import <MapKit/MapKit.h> @interface MyAnnotation : NSObject<MKAnnotation> @property(copy,nonatomic)NSString *title; @property(copy,nonatomic)NSString *subtitle; @property(assign,nonatomic)CLLocationCoordinate2D coordinate; @end
程序運行結果以下:編程
程序中還爲MKMapView指定了delegate,所以該delegate將會響應地圖位置改變、加載過程當中的相關事件,因此你們能夠看到Xcode的控制輸出消息。框架
2、根據地址定位工具
1.地址解析與反向地址解析學習
地址解析:把普通用戶能看懂的字符串地址轉換爲經度、緯度。atom
反向地址解析:把經度、緯度轉換成普通的字符串地址。spa
iOS爲地址解析提供了CLGeocoder工具類,該工具類提供了以下3種方法來進行地址解析和反向地址解析。3d
-geocodeAddressString:completionHandler: :根據給定的字符串地址進行解析,解析將會獲得該地址對應的經度、緯度信息。代理
-geocodeAddressString:inRegion:completonHandler: :根據給定的字符串進行解析,解析將會獲得該地址對應的經度、緯度信息。code
-reverseGeocodeLocation:completionHandler: :根據給定的經度、緯度地址方向解析獲得字符串地址。
通常來講:地址解析可能獲得多個結果——這是由於全球徹底可能有多個同名的地點;但反向地址解析通常只會獲得一個結果——由於根據指定經度、緯度獲得的地址一般是惟一的。
2.根據地址定位
根據地址定位的思路很是簡單,只要以下兩步便可。
(1)使用CLGeocoder根據字符串地址獲得該地址的經度、緯度。
(2)根據解析獲得的經度、緯度進行定位。
#import "ViewController.h" #import <MapKit/MapKit.h> #import <CoreLocation/CoreLocation.h> @interface ViewController ()<CLLocationManagerDelegate> @property(strong,nonatomic)CLLocationManager *locationManager; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 建立定位管理器 self.locationManager = [[CLLocationManager alloc]init]; //獲取用戶受權 [self.locationManager requestAlwaysAuthorization]; //獲取當前受權狀態 CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) { NSLog(@"受權經過"); } else { NSLog(@"受權不經過"); } //設置代理 self.locationManager.delegate = self; //設置經度 self.locationManager.desiredAccuracy =kCLLocationAccuracyBest; //開始定位 [self.locationManager startUpdatingLocation]; } #pragma mark - 定位管理器的代理方法 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { // NSLog(@"%@",locations); //取出位置信息 CLLocation *location = [locations lastObject]; //建立地理信息編解碼對象 CLGeocoder *geoCoder = [[CLGeocoder alloc]init]; //轉換位置信息 [geoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) { // NSLog(@"%@",placemarks[0]); CLPlacemark *placeMark = placemarks[0]; NSLog(@"%@%@",placeMark.country,placeMark.locality); }]; } -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"%@",error); } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { CLGeocoder *geoCoder = [[CLGeocoder alloc]init]; [geoCoder geocodeAddressString:@"西三旗" completionHandler:^(NSArray *placemarks, NSError *error) { if ([placemarks count] == 0) { NSLog(@"沒有找到相應的地理信息"); } else { CLPlacemark *placemark = [placemarks objectAtIndex:0]; //NSLog(@"%@",placeMark); // NSLog(@"%f,%f",placeMark.location.coordinate.latitude,placeMark.location.coordinate.longitude); MKMapItem *mapItem1 = [[MKMapItem alloc]initWithPlacemark:(MKPlacemark*)placemark]; [geoCoder geocodeAddressString:@"八達嶺長城" completionHandler:^(NSArray *placemarks, NSError *error) { MKMapItem *mapItem2 = [[MKMapItem alloc]initWithPlacemark:(MKPlacemark*)placemarks[0]]; //調用系統地圖打開一個位置 [MKMapItem openMapsWithItems:@[mapItem1,mapItem2] launchOptions:nil]; }]; } }]; } @end
3、在地圖上添加錨點
1.添加簡單地錨點
對於iOS的地圖而言,添加錨點只要調用MKMapView的-(void)addAnnotation:(id<MKAnnotation>)annotation方法便可,每調用一次,就像地圖添加一個錨點。MKAnnotation是一個協議,該協議中定義了3個屬性,用於設置和返回錨點的信息。
- coordinate:用於設置和返回錨點的位置。該屬性值必須是一個CLLocationCoordinate2D結構體變量,封裝了經度、緯度信息。
- title:用於設置和返回錨點的標題。
- subtitle:用於設置和返回錨點的副標題。
2.添加自定義錨點
錨點由兩部分組成。
錨點信息:錨點信息包括錨點的位置、標題、副標題等信息,這些信息有MKAnnotation對象表明。
錨點控件:錨點控件決定地圖上顯示的錨點外觀,包括錨點的圖片等。
iOS爲錨點控件提供了MKAnnotationView和MKPinAnnotationView,其中MKPinAnnotationView是MKAnnotationView的子類,而MKAnnotationView繼承了UIView——也就是說,它只是一個可視化的UI控件。
爲定製地圖上的錨點,須要完成以下兩步。
1.爲MKMapView指定delegate對象。
2.重寫delegatede-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation方法,該方法的返回值將做爲地圖上的錨點控件。
案例:在圖上添加錨點
#import "ViewController.h" #import <MapKit/MapKit.h> #import "MyAnnoation.h" @interface ViewController ()<MKMapViewDelegate> @property(strong,nonatomic)MKMapView *mapView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 建立mapView self.mapView = [[MKMapView alloc]initWithFrame:self.view.frame]; //設置地圖的類型 self.mapView.mapType = MKMapTypeStandard; [self.view addSubview:self.mapView]; self.mapView.delegate = self; //建立標註 MyAnnoation *annoation = [[MyAnnoation alloc]init]; annoation.coordinate= CLLocationCoordinate2DMake(40, 100); annoation.title = @"中國"; annoation.subtitle = @"好牛B的地方"; //添加標註 [self.mapView addAnnotation:annoation]; //讓地圖顯示標註的區域 [self.mapView setCenterCoordinate:annoation.coordinate animated:YES]; //添加手勢 UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)]; [self.mapView addGestureRecognizer:longPress]; } -(void)longPress:(UILongPressGestureRecognizer *)sender { //獲取當前位置 CGPoint location = [sender locationInView:self.view]; //轉換經緯度 CLLocationCoordinate2D coordinate =[self.mapView convertPoint:location toCoordinateFromView:self.mapView]; //建立標註 MyAnnoation *annotation = [[MyAnnoation alloc]init]; annotation.coordinate = coordinate; annotation.title = @"新的標註"; annotation.subtitle = @"待開發。。"; //添加標註 [self.mapView addAnnotation:annotation]; } #pragma mark - mapView代理方法 #pragma mark 顯示標註視圖 -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { static NSString *annotationID =@"annotation"; //先從重用隊列中去找 MKPinAnnotationView *view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationID]; //若是找不到,本身建立 if (!view) { view = [[MKPinAnnotationView alloc]init]; } //設置屬性 view.annotation = annotation; view.canShowCallout = YES;//顯示氣泡視圖 view.pinColor = MKPinAnnotationColorPurple;//設置大頭針顏色 //顯示圖片(這種方式設置圖片會取代大頭針) view.image = [UIImage imageNamed:@"0.png"]; //設置氣泡的輔助視圖(顯示圖片) view.leftCalloutAccessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"0.png"]]; return view; } #pragma mark 選中了標注後的處理 -(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view { NSLog(@"選中了標注"); } -(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view { NSLog(@"取消了標註"); } @end