转载

iOS_mapKit与Core Location

#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文件内容

#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

程序运行结果如下:

iOS_mapKit与Core Location

程序中还为MKMapView指定了delegate,因此该delegate将会响应地图位置改变、加载过程中的相关事件,所以大家可以看到Xcode的控制输出消息。

iOS_mapKit与Core Location

二、根据地址定位

1.地址解析与反向地址解析

地址解析:把普通用户能看懂的字符串地址转换为经度、纬度。

反向地址解析:把经度、纬度转换成普通的字符串地址。

iOS为地址解析提供了CLGeocoder工具类,该工具类提供了如下3种方法来进行地址解析和反向地址解析。

-geocodeAddressString:completionHandler: :根据给定的字符串地址进行解析,解析将会得到该地址对应的经度、纬度信息。

-geocodeAddressString:inRegion:completonHandler: :根据给定的字符串进行解析,解析将会得到该地址对应的经度、纬度信息。

-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 

三、在地图上添加锚点

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 
正文到此结束
Loading...