地圖應用經常會涉及到線路的繪制問題,ios下可以使用MKMapView進行地圖開發,使用MKOverlayView進行線路的繪制。
使用MKMapView添加MKMap.framework 和CoreLocation.framework並導入MapKit.h頭文件。
新建一個基於視圖的工程,修改頭文件:
- //
- // CloViewController.h
- // LocationMapTest
- //
- // Created by Cloay on 12-6-18.
- // Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
- //
-
- #import <UIKit/UIKit.h>
- #import <MapKit/MapKit.h>
- #import "CloMKAnnotation.h"
- @interface CloViewController : UIViewController<CLLocationManagerDelegate, MKMapViewDelegate, UIActionSheetDelegate>{
- MKMapView *cloMapView;
- MKPolyline *routeLine;
- }
-
- @property (nonatomic, strong) NSMutableArray *locations;
- @end
修改實現代碼,在.m中添加如下代碼:
- //
- // CloViewController.m
- // LocationMapTest
- //
- // Created by Cloay on 12-6-18.
- // Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
- //
-
- #import "CloViewController.h"
-
- @interface CloViewController ()
-
- @end
-
- @implementation CloViewController
- @synthesize locations;
-
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- cloMapView = [[MKMapView alloc] initWithFrame:[self.view bounds]];
- [cloMapView setMapType:MKMapTypeHybrid]; //設置地圖類型 地圖/衛星/兩者結合
- [cloMapView setShowSUSErLocation:YES]; //顯示當前位置
- [cloMapView setDelegate:self];
-
- CLLocationManager *locationManager = [[CLLocationManager alloc] init];
- //設置CLLocationManager實例委托和精度
- [locationManager setDelegate:self];
- [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
- //設置距離篩選器,表示至少移動100米才通知委托更新
- [locationManager setDistanceFilter:100.f];
- //啟動更新請求
- // [locationManager startUpdatingLocation];
-
- locations = [[NSMutableArray alloc] init];
- float latitude = 39.8127; //維度
- float longitude = 116.2967; //經度
- for (int i = 0; i < 10; i++) {
-
- [locations addObject:[NSString stringWithFormat:@"%f,%f", latitude + 0.01*i, longitude + 0.01*i]];
- // NSLog(@"locations:%i",locations.count);
- }
-
- //地圖初始
- CLLocationCoordinate2D coords;
- coords.latitude = 39.9127;
- coords.longitude = 116.3967;
- float zoomlevel = 0.22;
- MKCoordinateRegion region = MKCoordinateRegionMake(coords, MKCoordinateSpanMake(zoomlevel, zoomlevel));
- [cloMapView setRegion:[cloMapView regionThatFits:region] animated:YES];
-
- [cloMapView addOverlay:[self makePolylineWithLocations:locations]];
- [self.view addSubview:cloMapView];
-
- }
-
- - (void)viewDidUnload
- {
- [super viewDidUnload];
- // Release any retained subviews of the main view.
- cloMapView = nil;
- }
-
- - (void)dealloc{
- [cloMapView release];
- [super dealloc];
- }
-
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
- {
- return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
- }
-
-
- //顯示菜單選項
- - (void)showActionSheet :(id)sender{
- UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:nil
- delegate:self
- cancelButtonTitle:@"取消"
- destructiveButtonTitle:@"添加足跡"
- otherButtonTitles:@"分享",@"詳細",@"刪除", nil];
- [actionSheet setDelegate:self];
- [actionSheet showInView:self.view];
- [actionSheet release];
- }
-
- //根據坐標點生成線路
- - (MKPolyline *)makePolylineWithLocations:(NSMutableArray *)newLocations{
- MKMapPoint *pointArray = malloc(sizeof(CLLocationCoordinate2D)* newLocations.count);
- for(int i = 0; i < newLocations.count; i++)
- {
- // break the string down even further to latitude and longitude fields.
- NSString* currentPointString = [newLocations objectAtIndex:i];
- NSArray* latLonArr = [currentPointString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@","]];
- CLLocationDegrees latitude = [[latLonArr objectAtIndex:0] doubleValue];
- // NSLog(@"latitude-> %f", latitude);
- CLLocationDegrees longitude = [[latLonArr objectAtIndex:1] doubleValue];
- CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
- // NSLog(@"point-> %f", point.x);
-
- if (i == 0 || i == locations.count - 1) {//這裡只添加起點和終點作為測試
- CloMKAnnotation *ann = [[CloMKAnnotation alloc] init];
- [ann setCoordinate:coordinate];
- [ann setTitle:[NSString stringWithFormat:@"緯度:%f", latitude]];
- [ann setSubtitle:[NSString stringWithFormat:@"經度:%f", longitude]];
- [cloMapView addAnnotation:ann];
- }
- pointArray[i] = MKMapPointForCoordinate(coordinate);
- }
-
- routeLine = [MKPolyline polylineWithPoints:pointArray count:newLocations.count];
- free(pointArray);
- return routeLine;
- }
- #pragma mark-
- #pragma CLLocationManager delegate method
- //位置變化後會調用
- - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
- //可在此處更新用戶位置信息
- // cloMapView.userLocation
- NSLog(@"oldLocation:%@", [oldLocation description]);
- NSLog(@"newLocation:%@", [newLocation description]);
- NSLog(@"distance:%@", [newLocation distanceFromLocation:oldLocation]);
- //位置變化添加新位置點
- [locations addObject:[NSString stringWithFormat:@"%f,%f", newLocation.coordinate.latitude, newLocation.coordinate.longitude]];
- //刪除進線路,更新新軌跡
- [cloMapView removeOverlay:routeLine];
- [cloMapView addOverlay:[self makePolylineWithLocations:locations]];
-
- }
-
- #pragma MKMapView delegate method
- //添加坐標點大頭針
- - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
- if (![annotation isKindOfClass:[CloMKAnnotation class]]) {
- return nil;
- }
- static NSString *identifier = @"Annotation";
- MKPinAnnotationView *pinAnnotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
- if (pinAnnotationView == nil) {
- pinAnnotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier] autorelease];
- }
- pinAnnotationView.animatesDrop = YES;
- pinAnnotationView.canShowCallout = YES;
- pinAnnotationView.draggable = YES;
- UIButton *detailBtn = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
- [detailBtn addTarget:self action:@selector(showActionSheet:) forControlEvents:UIControlEventTouchUpInside];
- pinAnnotationView.rightCalloutAccessoryView = detailBtn;
-
- return pinAnnotationView;
- }
-
- - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState{
-
- }
-
- //畫線
- - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay{
- NSLog(@"return overLayView...");
- if ([overlay isKindOfClass:[MKPolyline class]]) {
- MKPolylineView *routeLineView = [[[MKPolylineView alloc] initWithPolyline:routeLine] autorelease];
- routeLineView.strokeColor = [UIColor blueColor];
- routeLineView.lineWidth = 3;
- return routeLineView;
- }
- return nil;
- }
-
- @end
這裡主要是為了測試,初始時 locations坐標點自定義的,實際中是根據用戶的位置動態生成的一系列坐標點。具體可在
- - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
函數中實現,如上代碼。
另外用戶的實時位置可用
- cloMapView.userLocation = newLocation進行設置,然後顯示在地圖上。
效果圖如下: