IOS定位核心與地圖
Core Location以及Map框架包通常能給我們的應用程序添加定位和地圖相關的服務。Core Location框架包通常是使用硬件設備來進行定位服務的,Map框架包通常能夠使你的應用程序做一些地圖展示與交互的相關功能。地圖的定位服務一般需要依賴設備的硬件組成部分。如果有定位的硬件設備,那么肯定是可以利用地圖框架包來進行地圖的一些相關的操作。
為了能夠在項目中使用到位置服務以及地圖展示的相關功能,你必須要導入Core Location 和Map這兩個框架包。如果你不知道怎么做,那么請參照如下步驟。
1.點擊你的項目工程圖標文件。
2.然后選擇target選項,如圖1所示。
3.然后選擇Build Phase模塊欄。
4.然后點開Link Binary With Libraries欄目,在點擊+號按鈕。
圖1 添加相關的框架包
5.添加MapKit.framework和CoreLocation.framework這兩個庫
6.在使用地圖和定位的地方,導入:
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
MKMapView是UIView的子類,所以可以像一個普通的View一樣添加到ViewController的View當中。
以下是相關的代碼
ViewController.h
-
#import <UIKit/UIKit.h>
-
#import <CoreLocation/CoreLocation.h>
-
#import <MapKit/MapKit.h>
-
#import "MyAnnotation.h"
-
-
@interface ViewController : UIViewController <MKMapViewDelegate,CLLocationManagerDelegate>
-
-
// MapView
-
@property (nonatomic,strong) MKMapView *myMapView;// 地圖控件
-
// LocationManager
-
@property (nonatomic,strong) CLLocationManager *myLocationManager;// 位置管理器
-
@property (nonatomic,strong) CLGeocoder *myGeoCoder ;// 地理位置和真實地址轉換
-
@end
ViewController.m
-
#import "ViewController.h"
-
#import "MKMapView+ZoomLevel.h"
-
-
@interface ViewController ()
-
-
@end
-
-
@implementation ViewController
-
-
@synthesize myMapView;
-
@synthesize myLocationManager;
-
@synthesize myGeoCoder;
-
- (void)viewDidLoad
-
{
-
[super viewDidLoad];
-
// Do any additional setup after loading the view, typically from a nib.
-
// 設置根View的背景顏色
-
self.view.backgroundColor = [UIColor colorWithRed:0x33 / 255.0f green:0x66 / 255.0f blue:0x99 / 255.0f alpha:0xFF / 255.0f];
-
// 初始化MapView并且設置MapView顯示的邊界
-
self.myMapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
-
// self.myMapView.mapType = MKMapTypeSatellite;
-
// self.myMapView.mapType = MKMapTypeHybrid;
-
self.myMapView.mapType = MKMapTypeStandard;
-
self.myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-
self.myMapView.delegate = self;
-
-
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(40.034122, 116.289574);
-
MyAnnotation *annotation = [[MyAnnotation alloc]initWithCoordinate:coordinate title:@"我的位置" subTitle:@"這里就是寡人的位置,嘿嘿!"];
-
annotation.pinColor = MKPinAnnotationColorPurple;
-
-
[self.myMapView addAnnotation:annotation];
-
-
-
[self.myMapView setShowsUserLocation:YES];
-
[self.myMapView setCenterCoordinate:coordinate zoomLevel:15 animated:YES];
-
-
[self.view addSubview:myMapView];
-
-
-
if([CLLocationManager locationServicesEnabled]){
-
self.myLocationManager = [[CLLocationManager alloc]init];
-
self.myLocationManager.delegate = self;
-
// // 提示用戶是否允許當前應用使用地理位置,已過時,在Info.plist中使用NSLocationUsageDescription鍵值替換
-
// self.myLocationManager.purpose = @"提示用戶是否允許當前應用使用位置,已過時";
-
[self.myLocationManager startUpdatingLocation];
-
}else{
-
NSLog(@">>>>>>>>>> 位置服務不可用 <<<<<<<<<<<<");
-
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"您的位置服務當前不可用,請打開位置服務后重試" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
-
[alertView show];
-
}
-
-
-
CLLocation *location = [[CLLocation alloc]initWithLatitude:40.034122 longitude:116.289574];
-
-
self.myGeoCoder = [[CLGeocoder alloc]init];
-
[self.myGeoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks,NSError *error){
-
if(error == nil && [placemarks count] > 0){
-
CLPlacemark *pm = [placemarks objectAtIndex:0];
-
NSLog(@"國家:%@" ,pm.country);
-
NSLog(@"郵編:%@",pm.postalCode);
-
NSLog(@"Locality:%@",pm.locality);
-
}else if(error == nil && [placemarks count] == 0){
-
NSLog(@"沒有地址返回");
-
}else if(error != nil){
-
NSLog(@"出錯了:%@",error);
-
}
-
}];
-
-
[self.myGeoCoder geocodeAddressString:@"中國北京市海淀區花園東路10號高德大廈" completionHandler:^(NSArray *placemarks,NSError *error){
-
if(nil == error && [placemarks count] > 0){
-
NSLog(@"placemarks count:%i",[placemarks count]);
-
CLPlacemark *pm = [placemarks objectAtIndex:0];
-
NSLog(@"longitude=%f",pm.location.coordinate.longitude);
-
NSLog(@"latitude=%f",pm.location.coordinate.latitude);
-
}else if([placemarks count] == 0 && error == nil){
-
NSLog(@"找不到給定地址的經緯度");
-
}else if(nil != nil){
-
NSLog(@"發生了錯誤:%@",error);
-
}
-
}];
-
-
-
-
-
-
}
-
-
- (void)didReceiveMemoryWarning
-
{
-
[super didReceiveMemoryWarning];
-
// Dispose of any resources that can be recreated.
-
-
}
-
-(void)viewDidUnload
-
{
-
[super viewDidUnload];
-
self.myMapView = nil;
-
[self.myLocationManager stopUpdatingLocation];
-
self.myLocationManager = nil;
-
}
-
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
-
{
-
return YES;
-
}
-
-
-
/*******************************************************************************************/
-
/*******************************************************************************************/
-
/*************************** MapView的Delegate的方法,全部都是Option的 *************************/
-
/*******************************************************************************************/
-
/*******************************************************************************************/
-
/*******************************************************************************************/
-
-
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
-
NSLog(@"mapView:regionWillChangeAnimated:方法被調用");
-
}
-
// 用戶的地理位置發生改變的時候調用
-
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
-
NSLog(@"mapView:regionDidChangeAnimated:方法被調用");
-
}
-
// 當地圖界面將要加載的時候將會調用這個方法
-
- (void)mapViewWillStartLoadingMap:(MKMapView *)mapView{
-
NSLog(@"mapViewWillStartLoadingMap:方法被調用");
-
}
-
// 當地圖界面加載完成的時候將要調用這個方法
-
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView{
-
NSLog(@"mapViewDidFinishLoadingMap:方法被調用");
-
}
-
// 當地圖界面加載失敗的時候調用這個方法
-
- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error{
-
NSLog(@"mapViewDidFailLoadingMap:withError:方法被調用,error is:%@" , [error description]);
-
}
-
// 添加到地圖的Annotation
-
// mapView:viewForAnnotation: provides the view for each annotation.
-
// This method may be called for all or some of the added annotations.
-
// For MapKit provided annotations (eg. MKUserLocation) return nil to use the MapKit provided annotation view.
-
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
-
{
-
MKAnnotationView *view = nil;
-
if([annotation isKindOfClass:[MyAnnotation class]] == NO){
-
return view;
-
}
-
if([mapView isEqual:self.myMapView] == NO){
-
return view;
-
}
-
-
MyAnnotation *senderAnnotation = (MyAnnotation*)annotation;
-
NSString *pinReusableIdentifier = [MyAnnotation reusableIdentifierForPinColor:senderAnnotation.pinColor];
-
MKPinAnnotationView *annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pinReusableIdentifier];
-
if(annotationView == nil){
-
annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:senderAnnotation reuseIdentifier:pinReusableIdentifier];
-
[annotationView setCanShowCallout:YES];
-
}
-
annotationView.pinColor = senderAnnotation.pinColor;
-
-
-
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
-
NSString *documentPath = [paths objectAtIndex:0];
-
-
-
NSString *cachePath = [documentPath stringByAppendingString:@"/images"];
-
NSString *cacheFile = [cachePath stringByAppendingString:@"icon.image"];
-
-
if([[NSFileManager defaultManager]fileExistsAtPath:cacheFile]){
-
UIImage *image = [UIImage imageWithContentsOfFile:cacheFile];
-
if(image != nil){
-
annotationView.image = image;
-
NSLog(@"通過本地設置圖片");
-
}else{
-
[self setAnnotionImageByUrl:annotationView cacheFile:cacheFile];
-
}
-
}else{
-
[self setAnnotionImageByUrl:annotationView cacheFile:cacheFile];
-
}
-
view = annotationView;
-
-
return view;
-
}
-
-
-(void) setAnnotionImageByUrl:(MKPinAnnotationView *)annotationView cacheFile:(NSString *) cacheFile{
-
NSLog(@"通過網絡設置文件");
-
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
-
dispatch_async(queue, ^{
-
-
-
-
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/img/duanwulogo_94a0060bda0885d1c2320ca0d7d7c342.gif"];
-
NSData *data = [NSData dataWithContentsOfURL:url];
-
-
if(data != nil){
-
-
[data writeToFile:cacheFile atomically:YES];
-
-
UIImage *image = [UIImage imageWithData:data];
-
dispatch_queue_t mainQueue = dispatch_get_main_queue();
-
dispatch_async(mainQueue, ^{
-
if(image != nil){
-
annotationView.image = image;
-
}
-
});
-
}
-
});
-
-
}
-
-
/**
-
-
// mapView:didAddAnnotationViews: is called after the annotation views have been added and positioned in the map.
-
// The delegate can implement this method to animate the adding of the annotations views.
-
// Use the current positions of the annotation views as the destinations of the animation.
-
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
-
-
// mapView:annotationView:calloutAccessoryControlTapped: is called when the user taps on left & right callout accessory UIControls.
-
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;
-
-
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(NA, 4_0);
-
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(NA, 4_0);
-
-
- (void)mapViewWillStartLocatingUser:(MKMapView *)mapView NS_AVAILABLE(NA, 4_0);
-
- (void)mapViewDidStopLocatingUser:(MKMapView *)mapView NS_AVAILABLE(NA, 4_0);
-
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation NS_AVAILABLE(NA, 4_0);
-
- (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error NS_AVAILABLE(NA, 4_0);
-
-
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
-
fromOldState:(MKAnnotationViewDragState)oldState NS_AVAILABLE(NA, 4_0);
-
-
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay NS_AVAILABLE(NA, 4_0);
-
-
// Called after the provided overlay views have been added and positioned in the map.
-
- (void)mapView:(MKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews NS_AVAILABLE(NA, 4_0);
-
-
- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated NS_AVAILABLE(NA, 5_0);
-
*/
-
-
-
-
-
/*******************************************************************************************/
-
/*******************************************************************************************/
-
/*************************** 位置相關 *************************/
-
/*******************************************************************************************/
-
/*******************************************************************************************/
-
/*******************************************************************************************/
-
-
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
-
{
-
NSLog(@"Latitude=%f",newLocation.coordinate.latitude);
-
NSLog(@"Longitude=%f",newLocation.coordinate.longitude);
-
}
-
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
-
{
-
-
NSLog(@"獲得位置失敗");
-
}
-
-
@end
MKMapView+ZoomLevel.h
-
#import <MapKit/MapKit.h>
-
-
@interface MKMapView (ZoomLevel)
-
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
-
zoomLevel:(NSUInteger)zoomLevel
-
animated:(BOOL)animated;
-
@end
MKMapView+ZoomLevel.m
-
#import "MKMapView+ZoomLevel.h"
-
-
@implementation MKMapView (ZoomLevel)
-
#define MERCATOR_OFFSET 268435456
-
#define MERCATOR_RADIUS 85445659.44705395
-
-
#pragma mark -
-
#pragma mark Map conversion methods
-
-
- (double)longitudeToPixelSpaceX:(double)longitude
-
{
-
return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
-
}
-
-
- (double)latitudeToPixelSpaceY:(double)latitude
-
{
-
return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
-
}
-
-
- (double)pixelSpaceXToLongitude:(double)pixelX
-
{
-
return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
-
}
-
-
- (double)pixelSpaceYToLatitude:(double)pixelY
-
{
-
return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
-
}
-
-
#pragma mark -
-
#pragma mark Helper methods
-
-
- (MKCoordinateSpan)coordinateSpanWithMapView:(MKMapView *)mapView
-
centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
-
andZoomLevel:(NSUInteger)zoomLevel
-
{
-
// convert center coordiate to pixel space
-
double centerPixelX = [self longitudeToPixelSpaceX:centerCoordinate.longitude];
-
double centerPixelY = [self latitudeToPixelSpaceY:centerCoordinate.latitude];
-
-
// determine the scale value from the zoom level
-
NSInteger zoomExponent = 20 - zoomLevel;
-
double zoomScale = pow(2, zoomExponent);
-
-
// scale the map's size in pixel space
-
CGSize mapSizeInPixels = mapView.bounds.size;
-
double scaledMapWidth = mapSizeInPixels.width * zoomScale;
-
double scaledMapHeight = mapSizeInPixels.height * zoomScale;
-
-
// figure out the position of the top-left pixel
-
double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
-
double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
-
-
// find delta between left and right longitudes
-
CLLocationDegrees minLng = [self pixelSpaceXToLongitude:topLeftPixelX];
-
CLLocationDegrees maxLng = [self pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
-
CLLocationDegrees longitudeDelta = maxLng - minLng;
-
-
// find delta between top and bottom latitudes
-
CLLocationDegrees minLat = [self pixelSpaceYToLatitude:topLeftPixelY];
-
CLLocationDegrees maxLat = [self pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
-
CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
-
-
// create and return the lat/lng span
-
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
-
return span;
-
}
-
-
#pragma mark -
-
#pragma mark Public methods
-
-
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
-
zoomLevel:(NSUInteger)zoomLevel
-
animated:(BOOL)animated
-
{
-
// clamp large numbers to 28
-
zoomLevel = MIN(zoomLevel, 28);
-
-
// use the zoom level to compute the region
-
MKCoordinateSpan span = [self coordinateSpanWithMapView:self centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];
-
MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
-
-
// set the region like normal
-
[self setRegion:region animated:animated];
-
}
-
-
-
@end
MyAnnotation.h
-
#import <Foundation/Foundation.h>
-
#import <CoreLocation/CoreLocation.h>
-
#import <MapKit/MapKit.h>
-
-
#define REUSABLE_PIN_RED @"Red"
-
#define REUSABLE_PIN_GREEN @"Green"
-
#define REUSABLE_PIN_PURPLE @"Purple"
-
-
@interface MyAnnotation : NSObject <MKAnnotation>
-
-
@property (nonatomic,readonly) CLLocationCoordinate2D coordinate;
-
@property (nonatomic, readonly, copy) NSString *title;
-
@property (nonatomic, readonly, copy) NSString *subtitle;
-
-
@property (nonatomic,unsafe_unretained) MKPinAnnotationColor pinColor;
-
-
-(id) initWithCoordinate:(CLLocationCoordinate2D) coordinate
-
title:(NSString*) paramTitle
-
subTitle:(NSString*) paramSubTitle;
-
// 得到顏色
-
+(NSString *) reusableIdentifierForPinColor:(MKPinAnnotationColor) paramColor;
-
-
@end
MyAnnotation.m
-
#import "MyAnnotation.h"
-
-
@implementation MyAnnotation
-
-
@synthesize coordinate,title,subtitle,pinColor;
-
-
-(id) initWithCoordinate
-
:(CLLocationCoordinate2D) paramCoordinate title:(NSString *)paramTitle subTitle:(NSString *)paramSubTitle
-
{
-
self = [super init];
-
if(self != nil){
-
coordinate = paramCoordinate;
-
title = paramTitle;
-
subtitle = paramSubTitle;
-
pinColor = MKPinAnnotationColorGreen;
-
}
-
-
return self;
-
}
-
-
+(NSString *)reusableIdentifierForPinColor:(MKPinAnnotationColor)paramColor
-
{
-
NSString *result = nil;
-
switch (paramColor) {
-
case MKPinAnnotationColorRed:
-
result = REUSABLE_PIN_RED;
-
break;
-
case MKPinAnnotationColorGreen:
-
result = REUSABLE_PIN_GREEN;
-
break;
-
case MKPinAnnotationColorPurple:
-
result = REUSABLE_PIN_PURPLE;
-
}
-
return result;
-
}
-
-
@end
注意,在使用用戶的位置的時候,系統會彈出是否允許應用使用位置的對話框,這個對話框中的提示文字,可以自己進行定義
在系統版本是6.0(包括6.0)以上的時候,在Info.plist文件中進行定義
<key>NSLocationUsageDescription</key>
<string>是否可以使用位置?如果需要使用本應用,是必須的!</string>
在6.0以下,這樣進行定義
- // // 提示用戶是否允許當前應用使用地理位置,已過時,在Info.plist中使用NSLocationUsageDescription鍵值替換
- // self.myLocationManager.purpose = @"提示用戶是否允許當前應用使用位置,已過時";
- 原文:http://www.cnblogs.com/xinye/archive/2013/06/13/3134746.html
文章列表