MKMapView地理编码(即根据地址来转换成坐标)

转载自:http://blog.sina.com.cn/s/blog_7b9d64af0101cays.html


CLGeocoder是iOS5中新加的一个类,其实跟之前的MKReverseGeocoder很相似,不过CLGeocoder是以一种block的形式来反向地理编码的。

看了官方的文档,MKReverseGeocoder在iOS5中被禁止了,但其实你还是可以使用这个的,只不过在未来的某个时间,会从文档中删除掉,而且苹果这次增加的CLGeocoder类,跟CoreLocation整合在了一起,其实想想也应该是一起的,定位,反向,本应该属于一个系列的。

CLGeocoder类中有几个方法,一个是把经纬度转化成大家能看懂的信息,比如:city,county,街道等等,CLGeocoder类中的其他几个方法也非常的给里,可以把city,county等信息直接转化为坐标,以前大家可能都去githud上下载过把地点名字转回到坐标的demo,现在不用了,apple直接提供了接口给大家使用,我也今天才发现的...哎



下面只抄录最重要的两段吧,需要的话可以具体到原文查看:

四、通过地理坐标(经纬度)得到地址信息

当我们得到了一组经纬度数据,并且想把这组数据解析出来得到一个实在的地理位置名称。  
通过一组经纬度数据得到一个实在的地理位置数据,我们通常称之为逆向地理编码。  

我们使用CLGeocoder类可以来完成这项任务!

贴:

#pragma mark - CLLocationManagerDelegate 定位服务


// 当获得了新的位置时,调用该方法

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation *)oldLocation{


    NSLog(@"Latitude = %f", newLocation.coordinate.latitude);

    NSLog(@"Longitude = %f", newLocation.coordinate.longitude);

    

    // 创建一个定位对象

    CLLocation *thelocation = [[CLLocation alloc]initWithLatitude:newLocation.coordinate.latitude

                                                        longitude:newLocation.coordinate.longitude];

    

    // 初始化一个反向地理编码对象

    self.myGeocoder = [[CLGeocoder allocinit];

    // 根据给定的经纬度来得到相应的地址信息

    [self.myGeocoder reverseGeocodeLocation:thelocation completionHandler:^(NSArray*placemarks, NSError *error) {

        if (error == nil && [placemarks count] > 0){

            

            // CLPlacemark 存储着相应的地址数据

            CLPlacemark *placemark = [placemarks objectAtIndex:0];


            NSLog(@"Country = %@", placemark.country);

            NSLog(@"Postal Code = %@"placemark.postalCode);

            NSLog(@"Locality = %@", placemark.locality);

        }

        else if (error == nil && [placemarks count] == 0){

            NSLog(@"No results were returned.");

        }

        else if (error != nil){

            NSLog(@"An error occurred = %@", error); }

    }];


}


有几点需要说明mark一下:

CLLocation:标识一个物理坐标对象。可以存储经纬度、海拔等信息。
CLGeocoder:这是一个提供物理地址(经纬度)到真实地址的转换的服务。换算出来的信息一般包括:国家、城市、州、街道等信息。而且,这个类需要基于联网状态下才能工作。因为数据都存储在苹果的数据库中。你懂的。

- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler 方法:

用来转换地理坐标到真实地址的方法。

location:要转换的地址坐标

completionHandler:一个Block,请求返回时调用

在看一下 CLGeocodeCompletionHandler这个Block的方法签名。

typedef void (^CLGeocodeCompletionHandler)(NSArray *placemarks, NSError *error);

placemarks:返回查询的地理信息

error:是否成功



五、通过地址信息得到地理坐标(经纬度)

当然,我们应该想到,地理坐标与地址信息之间应该能够互相转化。

反向地理编码是通过一组经纬度数据的到一个实在的地理位置名称。同样我们可以使用地理编码通过一个地理名称得到一组经纬度数据。 

CLGeocoder类可以来完成这项任务!

 

NSString *oreillyAddress =@"1005 Gravenstein Highway North, Sebastopol, CA 95472, USA";

    self.myGeocoder = [[CLGeocoder allocinit];

    [self.myGeocoder geocodeAddressString:oreillyAddress completionHandler:^(NSArray*placemarks, NSError *error) {

        

         if ([placemarks count] > 0 && error == nil){

             NSLog(@"Found %lu placemark(s).", (unsigned long)[placemarks count]);

             CLPlacemark *firstPlacemark = [placemarks objectAtIndex:0];

             NSLog(@"Longitude = %f", firstPlacemark.location.coordinate.longitude);

             NSLog(@"Latitude = %f", firstPlacemark.location.coordinate.latitude);

         } 

         else if ([placemarks count] == 0 &&

                  error == nil){

             NSLog(@"Found no placemarks.");

         }

         else if (error != nil){

             NSLog(@"An error occurred = %@", error);

         }

         }];


微笑




干脆把其余的也贴上来吧:

在iOS的应用中,有很多的应用都是使用了核心定位功能和地图的相关功能!

在实际开发中,也有很多相关的针对地图和定位来做的第三方插件!比如:百度地图。
关于第三方地图和定位插件,也是利用iOS中的相关API做的扩展和整合。具体,使用第三方的插件,就需要了解它们的API。

今天了解的就是iOS原始的核心定位和地图API!

什么是核心定位和地图

Core Location  以及  Map  框架包通常能给我们的应用程序添加定位和地图相关的服务。
Core Location 框架包通常是使用硬件设备来进行定位服务的,Map 框架包通常能够使你的应用程序做一些地图展示与交互的相关功能。  

iOS将这两个功能封装到了两个库中。当然,我们需要在项目中引入该库,才能享受相应的服务。
这两个库分别是:

核心定位:   #import

地图: #import


一、添加一个简单的地图视图

*.h 文件

#import

#import

#import


@interface MoreViewController :UIViewController<</span>MKMapViewDelegate,CLLocationManagerDelegate>{


}

@property (nonatomic, strong) MKMapView *myMapView;


@end



*.m 文件

- (void)viewDidLoad

{

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor whiteColor];

    

    // 初始化MKMapView

    self.myMapView = [[MKMapView alloc] initWithFrame:self.view.bounds];

    self.myMapView.mapType = MKMapTypeHybrid;

    [self.myMapView setDelegate:self];

    

    self.myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;

    [self.view addSubview:self.myMapView];

    

    

    // 返回用户是否开启了设备上的定位服务功能

    if ([CLLocationManager locationServicesEnabled]){

        self.myLocationManager = [[CLLocationManager allocinit];

        [self.myLocationManager setDelegate:self];

        [self.myLocationManager setPurpose:@"一些提示信息,告诉用户要开启定位服务功能"];

        

        // 开始更新地理位置,并根据更新结果执行CLLocationManagerDelegate方法

        [self.myLocationManager startUpdatingLocation];

    } else {

        

        NSLog(@"设备上的定位服务功能未开启!");

    }

       

}


说明:

在VC中,我们实现了两个协议,来捕捉相应的事件:
MKMapViewDelegate:关于地图的相关协议,定义了地图相关的协议方法。
CLLocationManagerDelegate :关于核心定位的相关协议。
这两个协议有很多方法,慢慢来体会吧。

二、为地图定义锚点

为了更好的封装性,我们自定义了一个锚点的自定义类,来控制锚点。
忽然有点迷茫,为什么要自定义锚点类呢?

@interface MyAnnotation : NSObject <</span>MKAnnotation>

因为 MKAnnotation 协议中的属性都是只读的!我们要方便的设置,就必须要覆盖 MKAnnotation 协议中的属性。

*.h 文件

#import

#import


@interface MyAnnotation : NSObject <<span style="color: #743fa4">MKAnnotation>{


}


// 特别要注意这个参数需要标示为只读类型的。因为 MKAnnotation 这个协议中定义的 Coordinate 也是只读类型的。

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

@property (nonatomic, copy, readonly) NSString *title;

@property (nonatomic, copy, readonly) NSString *subtitle;

 

@property (nonatomic, unsafe_unretained) MKPinAnnotationColor pinColor;// 气泡的颜色


// 初始化坐标(Coordinate

- (id) initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates title:(NSString*)paramTitle subTitle:(NSString *)paramSubTitle;

@end


*.m 文件

#import "MyAnnotation.h"


@implementation MyAnnotation

@synthesize coordinate;

@synthesize title;

@synthesize subtitle;

 

@synthesize pinColor;


- (id) initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates title:(NSString*)paramTitle subTitle:(NSString *)paramSubTitle{

    

    self = [super init];

    if (self != nil){

        coordinate = paramCoordinates;

        title = paramTitle;

        subtitle = paramSubTitle;

 

     pinColor = MKPinAnnotationColorGreen;// 定义默认颜色

    }

    return(self);

}


@end


这样,我们就能够调用我们自定义的锚点类来进行锚点的添加!

贴:

#pragma mark - CLLocationManagerDelegate 定位服务


// 当获得了新的位置时,调用该方法

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{


    NSLog(@"Latitude = %f", newLocation.coordinate.latitude);

    NSLog(@"Longitude = %f", newLocation.coordinate.longitude);

    

    // 定义一个2D坐标

    CLLocationCoordinate2D location =CLLocationCoordinate2DMake(newLocation.coordinate.latitude,newLocation.coordinate.longitude);

    

    // 初始化锚点,根据坐标,标题,副标题

    MyAnnotation *annotation =[[MyAnnotation alloc] initWithCoordinates:location

                                                                  title:@"My Title"

                                                               subTitle:@"My Sub Title"];


    // 为地图增加锚点

    [self.myMapView addAnnotation:annotation];


}


// 当无法获得位置时,调用该方法

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{


    NSLog(@"无法获取经纬度!");

}


#pragma mark - MKMapViewDelegate


// 当地图界面将要加载的时候会调用该方法

- (void)mapViewWillStartLoadingMap:(MKMapView *)mapView{

    

    NSLog(@"mapViewWillStartLoadingMap");


}


三、为地图定义不同颜色的锚点

原来,我也觉的挺复杂的。或者是什么其他的特殊方式。
但是,实际用了,感觉原理跟TableView中的返回Cell的代理方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


是一个尿性的!对,原理一样啊!

也就是实现 MKMapViewDelegate协议的 mapView方法:

- ( MKAnnotationView  *)mapView:( MKMapView  *)mapView viewForAnnotation:( id )annotation

多的所以也不解释了!

贴:

// 返回锚点(大头针)的View,根据坐标信息

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation{

    MKAnnotationView *result = nil;

    if ([annotation isKindOfClass:[MyAnnotation class]] == NO){

        return result;

    }

    if ([mapView isEqual:self.myMapView] == NO){

        return result;

    }

    MyAnnotation *senderAnnotation = (MyAnnotation *)annotation;

    

    // 获得锚点视图的颜色标识符

    // 重用MKPinAnnotationView(跟重用TableViewCell一个道理)

    

    NSString *pinReusableIdentifier = @"myAnnotation";

    

    MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [mapViewdequeueReusableAnnotationViewWithIdentifier:pinReusableIdentifier];

    if (annotationView == nil){

        

        annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:senderAnnotation reuseIdentifier:pinReusableIdentifier];

        [annotationView setCanShowCallout:YES];

    }


    annotationView.pinColor = senderAnnotation.pinColor;

    result = annotationView;

    return result;

}


你可能感兴趣的:(MKMapView地理编码(即根据地址来转换成坐标))