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 <MKAnnotation>) 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、取得真实地址 示例: 初始化MKReverseGeocoder MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:coordinates]; geocoder.delegate = self; [geocoder start]; 如果无法处理坐标,则调用reverseGeocoder:didFailWithError: 方法 - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error { NSLog(@”Error resolving coordinates: %@”, [error localizedDescription]); geocoder.delegate = nil; [geocoder autorelease]; } 如果成功,则调用reverseGeocoder:didFindPlacemark: 并把信息存储在MKPlacemark 中 didFindPlacemark:(MKPlacemark *)placemark { NSString *streetAddress = placemark.thoroughfare; NSString *city = placemark.locality; NSString *state = placemark.administrativeArea; NSString *zip = placemark.postalCode; // Do something with information geocoder.delegate = nil; [geocoder autorelease]; } ******************************************************* User Location: MapViews 用Core Location 来保存用户的路径并在地图上用一个蓝色的点表示出来。 你可以打开:mapView.showUserLocation = YES; 如果地图跟踪的是用户的未知,你可以通过只读的属性userLcoationVisible 来检测用户当前的位置是不是可见的。如果是YES,就是可见的。 你可以首先设定 showsUserLocation 为 YES来得到用户当前指定的坐标。然后访问userLocation 属性。这个属性返回一个MKUserLocation的实例变量。 MKUserLocation 是一个对象,有一个属性叫做location(CLLocation 类型)。 一个CLLocation 包含一个coordinate属性指向一个坐标的集合,所有的这些意味着你可以得到实际的坐标从MKUserLocation对象里:下属那个: CLLocationCoordinae2D coords = mapView.userLocation.location.coordinate; Coordinate Regions 如果你不告诉要显示什么或者找出世界上的当前某个具体的位置,那么map view 就不那么smart了。 通过map view, 做到这些工作的关键是 MKCoordinateRegion, 一个结构包含两部分数据,同时也定义了在map view种要显示的位置。 第一个成员是 center 。 这是另外一个结构类型是:CLLocationCoordinate2D, 一个CLLocationCoordinate2D包含两个浮点数值,经度和纬度。 这个点代表着map view的中间。 第二个叫做span。 是MKCoordinateSpan类型的结构。 它有两个程序叫做 latitudeDelta and longitudeDelta。 这两个程序被用来设定地图的缩放级别——在center周围应该显示多大的区域。 这些值代表经度和纬度的距离。如果latitudeDelta and longitudeDelta是很小的,地图将会被缩放的十分密集,如果大的话,地图将会被放大并显示一个较大的区域。 Convert degree to distance 每一个纬度代表69英里,或者是111km,不论你在那里。这样就使作为MKCoordinateSpan的参数的 latitudeDelta被传递的时候更容易计算。 经度所代表的距离就不是那么容易去计算了。为了做同样的计算,你必须使用纬度,因为它代表的距离取决与你在的地方相对与赤道的距离。 为了计算经度所代表的距离,你必须执行一些数学计算。 实际上apple已经提供了一些方法做这样的计算: MKCoordinateRegionmakeWithDistance() 创建一个region。 你提供坐标作为center , 距离(m)为经度和纬度的span。 例如创建一个region 来显示指定区域位置 1km。 通过调用 CLLocationCoordinate2D MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(center, 2000, 2000); 为了显示每个边周围的1km, 我们必须指定2000m 为每个span:1000m向左,1000m向右,1000m向上,1000m向下。 调用之后,viewRegion 将会包含一个格式化的MKCoordinateRegion,当然你可以使用了。剩下的就是比率转换问题了。 横总比: MKMapView 类优一个实例方法将会适应一个坐标区域来匹配map view的横纵比例。 regionThatFits: 使用的时候你只需在你创建的坐标区域里面传递,同时它会返回一个新的坐标区域来适应map view的比例。 MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion[; 设定区域显示: 一旦创建好坐标区域,你可以告诉map view 来显示通过setRegion:animated:方法创建的区域。如果你传递YES给第二个参数,mapView将会缩放移动等。 MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(center,2000,2000); MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion]; [mapView setRegion:adjustedRegion animated:YES]; 原文链接: http://palmsky.net/?p=3162 | 掌中天际
[_mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES]语句设置用户跟踪模式,用户跟踪模式有3种: MKUserTrackingModeNone 。没有用户跟踪模式; MKUserTrackingModeFollow 。可以跟踪用户的位置变化; MKUserTrackingModeFollowWithHeading 。可以跟踪用户的位置和方向变化;- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{ MKPinAnnotationView *annView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"snda.pin"]; if (annView == NULL) { annView = [[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"snda.pin"] autorelease]; } //annotation的相关设置(不是自定义的) annView.annotation = annotation; annView.canShowCallout = YES; annView.calloutOffset = CGPointMake(0, 0); annView.image = [UIImage imageNamed:@"capture-exposure-plus.png"]; annView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; return annView; }
- if ([annotation isKindOfClass:[MyMapAnnotation class]]) {
- static NSString* travellerAnnotationIdentifier = @"TravellerAnnotationIdentifier";
- MKPinAnnotationView* pinView = (MKPinAnnotationView *)
- [mapView dequeueReusableAnnotationViewWithIdentifier:travellerAnnotationIdentifier];
- if (!pinView)
- {
- // if an existing pin view was not available, create one
- MKAnnotationView* customPinView = [[[MKAnnotationView alloc]
- initWithAnnotation:annotation reuseIdentifier:travellerAnnotationIdentifier] autorelease];
- customPinView.pinColor = MKPinAnnotationColorPurple;
- customPinView.animatesDrop = YES; //如果不需要这个从天而降的效果,设置为NO即可。
- customPinView.canShowCallout = NO;
- return customPinView;
- }
- else
- {
- pinView.annotation = annotation;
- }
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation { if ([annotation isKindOfClass:[MKUserLocation class]]) return nil; if ([annotation isKindOfClass:[TravellerMapAnnotation class]]) { // try to dequeue an existing pin view first static NSString* travellerAnnotationIdentifier = @"TravellerAnnotationIdentifier"; MKPinAnnotationView* pinView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:travellerAnnotationIdentifier]; if (!pinView) { // if an existing pin view was not available, create one MKAnnotationView* customPinView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:travellerAnnotationIdentifier] autorelease]; customPinView.canShowCallout = YES; //很重要,运行点击弹出标签 UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; [rightButton addTarget:self action:@selector(showDetails:) //点击右边的按钮之后,显示另外一个页面 forControlEvents:UIControlEventTouchUpInside]; customPinView.rightCalloutAccessoryView = rightButton; MyMapAnnotation *travellerAnnotation = (TravellerMapAnnotation *)annotation; UIImageView *headImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:travellerAnnotation.headImage]]; customPinView.leftCalloutAccessoryView = headImage; //设置最左边的头像 [headImage release]; UIImage *image = [UIImage imageNamed:@"smileFace.png"]; customPinView.image = image; customPinView.opaque = YES; [travellerImage release]; return customPinView; } else { pinView.annotation = annotation; } return pinView; } return nil; }- return pinView;
- }
苹果地图资源链接:http://blog.csdn.net/wu11wuwu/article/details/7070034