地圖應用經常會涉及到線路的繪制問題,ios下可以使用MKMapView進行地圖開發,使用
MKOverlayView進行線路的繪制。
使用MKMapView添加MKMap.framework 和CoreLocation.framework並導入
MapKit.h頭文件。
新建一個基於視圖的工程,修改頭文件:
[cpp]
// 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
//
// 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中添加如下代碼:
[cpp]
// 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
//
// 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坐標點自定義的,實際中是根據用戶的位置動態生成的一系列坐標點。具體可在
[cpp] - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation函數中實現,如上代碼。
另外用戶的實時位置可用
[cpp] cloMapView.userLocation = newLocation進行設置,然後顯示在地圖上。
cloMapView.userLocation = newLocation進行設置,然後顯示在地圖上。
效果圖如下:
作者:Shang_515