第一种使用方式:
iOS地图位置开发
iPhone SDK提供了三个类来管理位置信息:CLLocation CLLocationManager 和 CLLHeading(不常用)。除了使用GPS来获取当前的位置信息外,iPhone也可以基于WiFi基站和无线发射塔来获得位置信息。GPS的精度最高,可以精确到米级别,但是也最耗电。
————CLLocation
CLLocation类代表一个位置信息,其中还包括了方向和速度。比如我在长安街188号以5公里/小时的速度往西走。CLLocation具有下面的属性和方法:
@property CLLocationCoordinate2D coordinate; //以经度和纬度表示的位置信息
@property CLLocationDistance altitude; //海拔
@property CLLocationAccuracy horizontalAccuracy; //水平精度(如:精确到米)
@property CLLocationAccuracy verticalAccuracy; //垂直精度
@property CLLocationDirection course; //方向
@property CLLocationSpeed speed; //速度
-(NSDate *)timeStamp;
//两个位置之间的距离
-(CLLocationDistance)distanceFromLocation:(CLLocation *)location;
————-CLLocationManager
CLLocationManager类管理和提供位置服务。它的属性和方法有:
@property CLLocation *location; //位置
@property id delegate;
@property CLLocationDistance distanceFilter; //距离过滤,比如:500以内
@property CLlocationAccuracy verticalAccuracy; //垂直精度
-(void) startUpdatingLocation; //开始更新位置(比如:你在往某个地方走)
-(void)stopUpdatingLocation; //停止更新位置
-(void)startUpdatingHeading; //开始更新方向(比如:你改往东走)
-(void)stopUpdatingHeading; //停止更新方向
CLLocationManagerDelegate是一个委托类。你的应用程序需要使用这个委托类。当用户改变位置的时候,CLLocationManager回调的方法是:
-(void)locationManager:(CLLocationManager )manager didUpdateToLocation:(CLLocation )newLocation fromLocation:(CLLocation *)oldLocation;
当用户改变方向的时候,所调用的方法是:
-(void)locationManager:(CLLocationManager )manager didUpdateHeading:(CLLHeading )newHeading;
当iPhone无法获得当前位置的信息时,所回调的方法是:
-(void)locationManager: (CLLocationManager )manager didFailLoadWithError:(NSError )error;
=========================================================================
下面我们来看一个位置类的基本步骤:
一、启动定位服务
CLLocationManager *locManager = [[CLLocationManager alloc] init];
locManager.delegate = self;
[locManager startUpdatingLocation];
二、获得位置信息
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation )newLocation fromLocation: (CLLocation )oldLocation
{
NSTimeInterval howRecent = [newLocation.timestamp timeIntervalSinceNow];
if(howRecent < -10) return ; //离上次更新的时间少于10秒
if(newLocation.horizontalAccuracy > 100) return; //精度> 100米
//经度和纬度
double lat = newLocation.coordinate.latitude;
double lon = newLocation.coordinate.longitude;
}
三、获得方向信息(比如往南走)
-(void)locationManager:(CLLocationManager )manager didUpdateHeading:(CLHeading )newHeading
{
//获得方向
CLLocationDirection heading = newHeading .trueHeading;
}
四、停止定位
[locManager stopUpdatingLocation];
你可以设置你想要的精度和距离过滤:
locManager.desiredAccuracy = kLLocationAccuracyBest;
locManager.distanceFilter = 1000;
MapKit框架:
主要提供了四个功能:显示地图、CLLocation和地址之间的转换、支持在地图上做标记(比如标记北京天安门广场)、把一个位置解析成地址(比如我在水立方,想要知道确切的地址信息)。
MKMapView类:主要是完成下述功能:
——-显示地图,比如:显示北京市的地图;
——-提供多种显示方式,比如标准地图格式,卫星地图等;
——-支持地图的放大缩小;
——-支持在地图上做标记,比如标记天安门广场;
——-在地图上显示手机所在的当前位置。
MKMapView类的属性有:
@property MKCoordinateRegin region; //地图所显示的区域
@property CLLocationCoordinate2D centerCoordinate; //经度和纬度确定的中心位置
@property MKMapView mapType; //地图的显示类型,如:卫星地图
@property NSArray *annotations; //地图上的标记
@property MKUserLocation userLocation; //用户位置
@property id delegate; //委托类
装载地图时的回调方法有:
-(void)mapViewWillStartLocationMap:(MKMapView *) mapView; //开始装载地图
-(void)mapViewDidFinishLocationMap:(MKMapView *)mapView; //结束装载地图
-(void)mapVewDidFailLoadingMap:(MKMapView )mapView withError:(NSError )error; //装载失败
当位置发生转变时的回调方法:
-(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated; //将要更改
-(void)mapView: (MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated; //已经更改
MKPlacemark、MKUserLocation和MKReverseGeocoder
在地图上做标记是通过MKPlacemark类来完成的。这个类使用(符合)MKAnnotation协议。MKAnnotation包含了多个属性,如:位置(经纬度,CLLocationCoordinate2D类型)、文字标记信息(NSString类型)等。
MKPlacemark保存了位置(经纬度)和地址(字典类)之间的映射。下面是它的初始化方法:
-(void)initWithCoordinate:(CLLocationCoordinate2D )coordinate addressDictionary:(NSDictionary )dictionary;
MKUserLocation就是指手机的当前位置,它是MKAnnotation的一个特别案例(因为MKAnnotation可以是地图上的任何标记,而MKUserLocation只是标记了地图上手机所在的当前位置)。这个类包含了多个属性:手机的位置(类型为CLLocation)、位置文字信息(类型为NSString)等。
MKPlacemark保存了位置(经纬度)和地址之间的映射。那么,有没有工具在这两者之间做转换呢?这就是MKRecerseGeocoder.给定一个位置信息,这个类可以返回相应的地址信息。MKReverseGeocoder的初始化方法为:
-(void)initWithCoodinate:(CLLocationCoordinate2D)coordinate;
下面是MKReverseGeocoder常用的一些属性和方法:
@property id delegate; //委托
-(void)start; //开始转换
-(void)cancel; //取消转换
回调的方法有:
-(void)reverseGeocoder:(MKReverseGeocoder ) geocoded didFindPlacemark:(MKPlacemark )placemark; //转换成功
-(void)reverseGeocoder : (MKReverseGeocoder )geocoded didFailWithError:(NSError )error; //转换失败
第二种方式:
1、概述
插入MapView,设置Delegate(一般为Controller),Annotations记录兴趣位置点(AnnotationView用来显示兴趣位置点),annotation是可选的,选中的annotation会显示callout,用来显示信息。2、设置地图显示类型:
mapView.mapType = MKMapTypeStandard;
mapView.mapType = MKMapTypeSatellite;
mapView.mapType = MKMapTypeHybrid;3、显示用户位置
设置为可以显示用户位置:
mapView.showsUserLocation = YES;
判断用户当前位置是否可见(只读属性):
userLocationVisible
得到用户位置坐标:当userLocationVisible为YES时
CLLocationCoordinate2D coords = mapView.userLocation.location.coordinate;4、坐标范围
MKCoordinateRegion用来设置坐标显示范围。
包括两部分:Center(CLLocationCoordinate2D struct,包括latitude和longitude),坐标中心
和Span(MKCoordinateSpan struct,包括latitudeDelta和longitudeDelta),缩放级别
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(center,2000, 2000);
以上代码创建一个以center为中心,上下各1000米,左右各1000米得区域,但其是一个矩形,不符合MapView的横纵比例
MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion];
以上代码创建出来一个符合MapView横纵比例的区域
[mapView setRegion:adjustedRegion animated:YES];
以上代码为:最终显示该区域5、Delegate
使用MapView须符合MKMapViewDelegate协议5.1、地图加载Delegate
当需要从Google服务器取得新地图时
mapViewWillStartLoadingMap:
当成功地取得地图后
mapViewDidFinishLoadingMap:
当取得地图失败后(建议至少要实现此方法)
mapViewDidFailLoadingMap:withError:5.2、范围变化Delegate
当手势开始(拖拽,放大,缩小,双击)
mapView:regionWillChangeAnimated:
当手势结束(拖拽,放大,缩小,双击)
mapView:regionDidChangeAnimated: 判断坐标是否在MapView显示范围内:
CLLocationDegrees leftDegrees = mapView.region.center.longitude –(mapView.region.span.longitudeDelta / 2.0);
CLLocationDegrees rightDegrees = mapView.region.center.longitude +(mapView.region.span.longitudeDelta / 2.0);
CLLocationDegrees bottomDegrees = mapView.region.center.latitude –(mapView.region.span.latitudeDelta / 2.0);
CLLocationDegrees topDegrees = self.region.center.latitude +(mapView.region.span.latitudeDelta / 2.0); if (leftDegrees > rightDegrees) { // Int’l Date Line in View
leftDegrees = -180.0 – leftDegrees;
if (coords.longitude > 0) // coords to West of Date Line
coords.longitude = -180.0 – coords.longitude;
}
If (leftDegrees <= coords.longitude && coords.longitude <= rightDegrees && bottomDegrees <= coords.latitude && coords.latitude <= topDegrees) {
// 坐标在范围内
}6、Annotation Annotation包含两部分:Annotation Object和Annotation View Annotation Object必须符合协议MKAnnotation,包括两个方法:title和subtitle,分别用于显示注释的标题和子标题。还有 coordinate属性,返回CLLocationCoordinate2D,表示Annotation的位置
然后,需使用mapView:viewForAnnotation: 方法来返回MKAnnotationView或者MKAnnotationView的子类用来显示Annotation(注意:这里显示的不是选中Annotation后的弹出框) 你可以子类化MKAnnotationView,然后再drawRect:方法里面进行自己的绘制动作(这个方法很蠢) 你完全可以实例化一个MKAnnotationView,然后更改它的image属性,这样很简单。 7、添加移除Annotation
添加一个Annotation
[mapView addAnnotation:annotation];
添加一个Annotation数组
[mapView addAnnotations:[NSArray arrayWithObjects:annotation1, annotation2, nil]];
移除一个Annotation
removeAnnotation:
移除一个Annotation数组
removeAnnotations:
移除所有Annotation
[mapView removeAnnotations:mapView.annotations];8、选中Annotation
一次只能有一个Annotation被选中,选中后会出现CallOut(浮动框)
简单的CallOut显示Title和SubTitle,但你也可以自定义一个UIView作为CallOut(与自定义的TableViewCell一样)
可通过代码选中Annotation:
selectAnnotation:animated:
或者取消选择:
deselectAnnotation:animated: 9、显示Annotation
通过mapView:viewForAnnotation: 方法显示Annotation,每在MapView中加入一个Annotation,就会调用此方法
示例(与tableView:cellForRowAtIndexPath: 很相似)
- (MKAnnotationView ) mapView:(MKMapView )theMapView viewForAnnotation:(id ) annotation {
static NSString *placemarkIdentifier = @”my annotation identifier”;
if ([annotation isKindOfClass:[MyAnnotation class]]) {
MKAnnotationView *annotationView = [theMapView dequeueReusableAnnotationViewWithIdentifier:placemarkIdentifier];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:placemarkIdentifier];
annotationView.image = [UIImage imageNamed:@”blood_orange.png”];
}
else
annotationView.annotation = annotation;
return annotationView;
}
return nil;
}10、取得真实地址
示例:
初始化MKReverseGeocoderMKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:coordinates];
geocoder.delegate = self;
[geocoder start];
如果无法处理坐标,则调用reverseGeocoder:didFailWithError: 方法