IOS定位核心与地图

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

  1. #import <UIKit/UIKit.h>
  2. #import <CoreLocation/CoreLocation.h>
  3. #import <MapKit/MapKit.h>
  4. #import "MyAnnotation.h"
  5.  
  6. @interface ViewController : UIViewController <MKMapViewDelegate,CLLocationManagerDelegate>
  7.  
  8. // MapView
  9. @property (nonatomic,strong) MKMapView *myMapView;// 地图控件
  10. // LocationManager
  11. @property (nonatomic,strong) CLLocationManager *myLocationManager;// 位置管理器
  12. @property (nonatomic,strong) CLGeocoder *myGeoCoder ;// 地理位置和真实地址转换
  13. @end

ViewController.m

  1. #import "ViewController.h"
  2. #import "MKMapView+ZoomLevel.h"
  3.  
  4. @interface ViewController ()
  5.  
  6. @end
  7.  
  8. @implementation ViewController
  9.  
  10. @synthesize myMapView;
  11. @synthesize myLocationManager;
  12. @synthesize myGeoCoder;
  13. - (void)viewDidLoad
  14. {
  15.     [super viewDidLoad];
  16.    // Do any additional setup after loading the view, typically from a nib.
  17.     // 设置根View的背景颜色
  18.     self.view.backgroundColor = [UIColor colorWithRed:0x33 / 255.0f green:0x66 / 255.0f blue:0x99 / 255.0f alpha:0xFF / 255.0f];
  19.     // 初始化MapView并且设置MapView显示的边界
  20.     self.myMapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
  21. // self.myMapView.mapType = MKMapTypeSatellite;
  22. // self.myMapView.mapType = MKMapTypeHybrid;
  23.     self.myMapView.mapType = MKMapTypeStandard;
  24.     self.myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  25.     self.myMapView.delegate = self;
  26.  
  27.     CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(40.034122, 116.289574);
  28.     MyAnnotation *annotation = [[MyAnnotation alloc]initWithCoordinate:coordinate title:@"我的位置" subTitle:@"这里就是寡人的位置,嘿嘿!"];
  29.     annotation.pinColor = MKPinAnnotationColorPurple;
  30.  
  31.     [self.myMapView addAnnotation:annotation];
  32.  
  33.  
  34.     [self.myMapView setShowsUserLocation:YES];
  35.     [self.myMapView setCenterCoordinate:coordinate zoomLevel:15 animated:YES];
  36.  
  37.     [self.view addSubview:myMapView];
  38.  
  39.  
  40.     if([CLLocationManager locationServicesEnabled]){
  41.         self.myLocationManager = [[CLLocationManager alloc]init];
  42.         self.myLocationManager.delegate = self;
  43. // // 提示用户是否允许当前应用使用地理位置,已过时,在Info.plist中使用NSLocationUsageDescription键值替换
  44. // self.myLocationManager.purpose = @"提示用户是否允许当前应用使用位置,已过时";
  45.         [self.myLocationManager startUpdatingLocation];
  46.     }else{
  47.         NSLog(@">>>>>>>>>> 位置服务不可用 <<<<<<<<<<<<");
  48.         UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"您的位置服务当前不可用,请打开位置服务后重试" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
  49.         [alertView show];
  50.     }
  51.  
  52.  
  53.     CLLocation *location = [[CLLocation alloc]initWithLatitude:40.034122 longitude:116.289574];
  54.  
  55.     self.myGeoCoder = [[CLGeocoder alloc]init];
  56.     [self.myGeoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks,NSError *error){
  57.         if(error == nil && [placemarks count] > 0){
  58.             CLPlacemark *pm = [placemarks objectAtIndex:0];
  59.             NSLog(@"国家:%@" ,pm.country);
  60.             NSLog(@"邮编:%@",pm.postalCode);
  61.             NSLog(@"Locality:%@",pm.locality);
  62.         }else if(error == nil && [placemarks count] == 0){
  63.             NSLog(@"没有地址返回");
  64.         }else if(error != nil){
  65.             NSLog(@"出错了:%@",error);
  66.         }
  67.     }];
  68.  
  69.     [self.myGeoCoder geocodeAddressString:@"中国北京市海淀区花园东路10号高德大厦" completionHandler:^(NSArray *placemarks,NSError *error){
  70.         if(nil == error && [placemarks count] > 0){
  71.             NSLog(@"placemarks count:%i",[placemarks count]);
  72.             CLPlacemark *pm = [placemarks objectAtIndex:0];
  73.             NSLog(@"longitude=%f",pm.location.coordinate.longitude);
  74.             NSLog(@"latitude=%f",pm.location.coordinate.latitude);
  75.         }else if([placemarks count] == 0 && error == nil){
  76.             NSLog(@"找不到给定地址的经纬度");
  77.         }else if(nil != nil){
  78.             NSLog(@"发生了错误:%@",error);
  79.         }
  80.     }];
  81.  
  82.  
  83.  
  84.  
  85.  
  86. }
  87.  
  88. - (void)didReceiveMemoryWarning
  89. {
  90.     [super didReceiveMemoryWarning];
  91.     // Dispose of any resources that can be recreated.
  92.  
  93. }
  94. -(void)viewDidUnload
  95. {
  96.     [super viewDidUnload];
  97.     self.myMapView = nil;
  98.     [self.myLocationManager stopUpdatingLocation];
  99.     self.myLocationManager = nil;
  100. }
  101. -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
  102. {
  103.     return YES;
  104. }
  105.  
  106.  
  107. /*******************************************************************************************/
  108. /*******************************************************************************************/
  109. /*************************** MapView的Delegate的方法,全部都是Option的 *************************/
  110. /*******************************************************************************************/
  111. /*******************************************************************************************/
  112. /*******************************************************************************************/
  113.  
  114. - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
  115.     NSLog(@"mapView:regionWillChangeAnimated:方法被调用");
  116. }
  117. // 用户的地理位置发生改变的时候调用
  118. - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
  119.     NSLog(@"mapView:regionDidChangeAnimated:方法被调用");
  120. }
  121. // 当地图界面将要加载的时候将会调用这个方法
  122. - (void)mapViewWillStartLoadingMap:(MKMapView *)mapView{
  123.     NSLog(@"mapViewWillStartLoadingMap:方法被调用");
  124. }
  125. // 当地图界面加载完成的时候将要调用这个方法
  126. - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView{
  127.     NSLog(@"mapViewDidFinishLoadingMap:方法被调用");
  128. }
  129. // 当地图界面加载失败的时候调用这个方法
  130. - (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error{
  131.     NSLog(@"mapViewDidFailLoadingMap:withError:方法被调用,error is:%@" , [error description]);
  132. }
  133. // 添加到地图的Annotation
  134. // mapView:viewForAnnotation: provides the view for each annotation.
  135. // This method may be called for all or some of the added annotations.
  136. // For MapKit provided annotations (eg. MKUserLocation) return nil to use the MapKit provided annotation view.
  137. - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
  138. {
  139.     MKAnnotationView *view = nil;
  140.     if([annotation isKindOfClass:[MyAnnotation class]] == NO){
  141.         return view;
  142.     }
  143.     if([mapView isEqual:self.myMapView] == NO){
  144.         return view;
  145.     }
  146.  
  147.     MyAnnotation *senderAnnotation = (MyAnnotation*)annotation;
  148.     NSString *pinReusableIdentifier = [MyAnnotation reusableIdentifierForPinColor:senderAnnotation.pinColor];
  149.     MKPinAnnotationView *annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pinReusableIdentifier];
  150.     if(annotationView == nil){
  151.         annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:senderAnnotation reuseIdentifier:pinReusableIdentifier];
  152.         [annotationView setCanShowCallout:YES];
  153.     }
  154.     annotationView.pinColor = senderAnnotation.pinColor;
  155.  
  156.  
  157.     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  158.     NSString *documentPath = [paths objectAtIndex:0];
  159.  
  160.  
  161.     NSString *cachePath = [documentPath stringByAppendingString:@"/images"];
  162.     NSString *cacheFile = [cachePath stringByAppendingString:@"icon.image"];
  163.  
  164.     if([[NSFileManager defaultManager]fileExistsAtPath:cacheFile]){
  165.         UIImage *image = [UIImage imageWithContentsOfFile:cacheFile];
  166.         if(image != nil){
  167.             annotationView.image = image;
  168.             NSLog(@"通过本地设置图片");
  169.         }else{
  170.             [self setAnnotionImageByUrl:annotationView cacheFile:cacheFile];
  171.         }
  172.     }else{
  173.         [self setAnnotionImageByUrl:annotationView cacheFile:cacheFile];
  174.     }
  175.     view = annotationView;
  176.  
  177.     return view;
  178. }
  179.  
  180. -(void) setAnnotionImageByUrl:(MKPinAnnotationView *)annotationView cacheFile:(NSString *) cacheFile{
  181.     NSLog(@"通过网络设置文件");
  182.     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  183.     dispatch_async(queue, ^{
  184.  
  185.  
  186.  
  187.         NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/img/duanwulogo_94a0060bda0885d1c2320ca0d7d7c342.gif"];
  188.         NSData *data = [NSData dataWithContentsOfURL:url];
  189.  
  190.         if(data != nil){
  191.  
  192.             [data writeToFile:cacheFile atomically:YES];
  193.  
  194.             UIImage *image = [UIImage imageWithData:data];
  195.             dispatch_queue_t mainQueue = dispatch_get_main_queue();
  196.             dispatch_async(mainQueue, ^{
  197.                 if(image != nil){
  198.                     annotationView.image = image;
  199.                 }
  200.             });
  201.         }
  202.     });
  203.  
  204. }
  205.  
  206. /**
  207.  
  208. // mapView:didAddAnnotationViews: is called after the annotation views have been added and positioned in the map.
  209. // The delegate can implement this method to animate the adding of the annotations views.
  210. // Use the current positions of the annotation views as the destinations of the animation.
  211. - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
  212.  
  213. // mapView:annotationView:calloutAccessoryControlTapped: is called when the user taps on left & right callout accessory UIControls.
  214. - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;
  215.  
  216. - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(NA, 4_0);
  217. - (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(NA, 4_0);
  218.  
  219. - (void)mapViewWillStartLocatingUser:(MKMapView *)mapView NS_AVAILABLE(NA, 4_0);
  220. - (void)mapViewDidStopLocatingUser:(MKMapView *)mapView NS_AVAILABLE(NA, 4_0);
  221. - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation NS_AVAILABLE(NA, 4_0);
  222. - (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error NS_AVAILABLE(NA, 4_0);
  223.  
  224. - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
  225. fromOldState:(MKAnnotationViewDragState)oldState NS_AVAILABLE(NA, 4_0);
  226.  
  227. - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay NS_AVAILABLE(NA, 4_0);
  228.  
  229. // Called after the provided overlay views have been added and positioned in the map.
  230. - (void)mapView:(MKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews NS_AVAILABLE(NA, 4_0);
  231.  
  232. - (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated NS_AVAILABLE(NA, 5_0);
  233. */
  234.  
  235.  
  236.  
  237.  
  238. /*******************************************************************************************/
  239. /*******************************************************************************************/
  240. /*************************** 位置相关 *************************/
  241. /*******************************************************************************************/
  242. /*******************************************************************************************/
  243. /*******************************************************************************************/
  244.  
  245. -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
  246. {
  247.     NSLog(@"Latitude=%f",newLocation.coordinate.latitude);
  248.     NSLog(@"Longitude=%f",newLocation.coordinate.longitude);
  249. }
  250. -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
  251. {
  252.  
  253.     NSLog(@"获得位置失败");
  254. }
  255.  
  256. @end

MKMapView+ZoomLevel.h

  1. #import <MapKit/MapKit.h>
  2.  
  3. @interface MKMapView (ZoomLevel)
  4. - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
  5.                   zoomLevel:(NSUInteger)zoomLevel
  6.                    animated:(BOOL)animated;
  7. @end

MKMapView+ZoomLevel.m

  1. #import "MKMapView+ZoomLevel.h"
  2.  
  3. @implementation MKMapView (ZoomLevel)
  4. #define MERCATOR_OFFSET 268435456
  5. #define MERCATOR_RADIUS 85445659.44705395
  6.  
  7. #pragma mark -
  8. #pragma mark Map conversion methods
  9.  
  10. - (double)longitudeToPixelSpaceX:(double)longitude
  11. {
  12.     return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
  13. }
  14.  
  15. - (double)latitudeToPixelSpaceY:(double)latitude
  16. {
  17.     return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
  18. }
  19.  
  20. - (double)pixelSpaceXToLongitude:(double)pixelX
  21. {
  22.     return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
  23. }
  24.  
  25. - (double)pixelSpaceYToLatitude:(double)pixelY
  26. {
  27.     return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
  28. }
  29.  
  30. #pragma mark -
  31. #pragma mark Helper methods
  32.  
  33. - (MKCoordinateSpan)coordinateSpanWithMapView:(MKMapView *)mapView
  34.                              centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
  35.                                  andZoomLevel:(NSUInteger)zoomLevel
  36. {
  37.     // convert center coordiate to pixel space
  38.     double centerPixelX = [self longitudeToPixelSpaceX:centerCoordinate.longitude];
  39.     double centerPixelY = [self latitudeToPixelSpaceY:centerCoordinate.latitude];
  40.  
  41.     // determine the scale value from the zoom level
  42.     NSInteger zoomExponent = 20 - zoomLevel;
  43.     double zoomScale = pow(2, zoomExponent);
  44.  
  45.     // scale the map's size in pixel space
  46.     CGSize mapSizeInPixels = mapView.bounds.size;
  47.     double scaledMapWidth = mapSizeInPixels.width * zoomScale;
  48.     double scaledMapHeight = mapSizeInPixels.height * zoomScale;
  49.  
  50.     // figure out the position of the top-left pixel
  51.     double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
  52.     double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
  53.  
  54.     // find delta between left and right longitudes
  55.     CLLocationDegrees minLng = [self pixelSpaceXToLongitude:topLeftPixelX];
  56.     CLLocationDegrees maxLng = [self pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
  57.     CLLocationDegrees longitudeDelta = maxLng - minLng;
  58.  
  59.     // find delta between top and bottom latitudes
  60.     CLLocationDegrees minLat = [self pixelSpaceYToLatitude:topLeftPixelY];
  61.     CLLocationDegrees maxLat = [self pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
  62.     CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
  63.  
  64.     // create and return the lat/lng span
  65.     MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
  66.     return span;
  67. }
  68.  
  69. #pragma mark -
  70. #pragma mark Public methods
  71.  
  72. - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
  73.                   zoomLevel:(NSUInteger)zoomLevel
  74.                    animated:(BOOL)animated
  75. {
  76.     // clamp large numbers to 28
  77.     zoomLevel = MIN(zoomLevel, 28);
  78.  
  79.     // use the zoom level to compute the region
  80.     MKCoordinateSpan span = [self coordinateSpanWithMapView:self centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];
  81.     MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
  82.  
  83.     // set the region like normal
  84.     [self setRegion:region animated:animated];
  85. }
  86.  
  87.  
  88. @end

MyAnnotation.h

  1. #import <Foundation/Foundation.h>
  2. #import <CoreLocation/CoreLocation.h>
  3. #import <MapKit/MapKit.h>
  4.  
  5. #define REUSABLE_PIN_RED @"Red"
  6. #define REUSABLE_PIN_GREEN @"Green"
  7. #define REUSABLE_PIN_PURPLE @"Purple"
  8.  
  9. @interface MyAnnotation : NSObject <MKAnnotation>
  10.  
  11. @property (nonatomic,readonly) CLLocationCoordinate2D coordinate;
  12. @property (nonatomic, readonly, copy) NSString *title;
  13. @property (nonatomic, readonly, copy) NSString *subtitle;
  14.  
  15. @property (nonatomic,unsafe_unretained) MKPinAnnotationColor pinColor;
  16.  
  17. -(id) initWithCoordinate:(CLLocationCoordinate2D) coordinate
  18.                    title:(NSString*) paramTitle
  19.                 subTitle:(NSString*) paramSubTitle;
  20. // 得到颜色
  21. +(NSString *) reusableIdentifierForPinColor:(MKPinAnnotationColor) paramColor;
  22.  
  23. @end

MyAnnotation.m

  1. #import "MyAnnotation.h"
  2.  
  3. @implementation MyAnnotation
  4.  
  5. @synthesize coordinate,title,subtitle,pinColor;
  6.  
  7. -(id) initWithCoordinate
  8. :(CLLocationCoordinate2D) paramCoordinate title:(NSString *)paramTitle subTitle:(NSString *)paramSubTitle
  9. {
  10.     self = [super init];
  11.     if(self != nil){
  12.         coordinate = paramCoordinate;
  13.         title = paramTitle;
  14.         subtitle = paramSubTitle;
  15.         pinColor = MKPinAnnotationColorGreen;
  16.     }
  17.  
  18.     return self;
  19. }
  20.  
  21. +(NSString *)reusableIdentifierForPinColor:(MKPinAnnotationColor)paramColor
  22. {
  23.     NSString *result = nil;
  24.     switch (paramColor) {
  25.         case MKPinAnnotationColorRed:
  26.             result = REUSABLE_PIN_RED;
  27.             break;
  28.         case MKPinAnnotationColorGreen:
  29.             result = REUSABLE_PIN_GREEN;
  30.             break;
  31.         case MKPinAnnotationColorPurple:
  32.             result = REUSABLE_PIN_PURPLE;
  33.     }
  34.     return result;
  35. }
  36.  
  37. @end

注意,在使用用户的位置的时候,系统会弹出是否允许应用使用位置的对话框,这个对话框中的提示文字,可以自己进行定义

在系统版本是6.0(包括6.0)以上的时候,在Info.plist文件中进行定义

<key>NSLocationUsageDescription</key>

<string>是否可以使用位置?如果需要使用本应用,是必须的!</string>

在6.0以下,这样进行定义

  1. // // 提示用户是否允许当前应用使用地理位置,已过时,在Info.plist中使用NSLocationUsageDescription键值替换
  2. // self.myLocationManager.purpose = @"提示用户是否允许当前应用使用位置,已过时";
  3. 原文:http://www.cnblogs.com/xinye/archive/2013/06/13/3134746.html
原文地址:https://www.cnblogs.com/langtianya/p/4006916.html