一、定位服务介绍
iOS中有三个定位服务组件:
(1)Wifi定位,通过查询一个Wifi路由器的地理位置的信息。比较省电,iPod touch和iPad也可以采用。
(2)蜂窝基站定位,通过移动运用商基站定位。也适合有3G版本的iPod touch和iPad
(3)GPS卫星定位,通过3-4颗GPS定位位置定位,最为准确,但是耗电量大,不能遮挡。
二、项目引用库介绍
(1)CoreLocation.framework 是开发定位服务应用程序的框架
(2)MapKit.framework 是开发地图应用的框架
三、位置模拟
模拟器定位有6个选项:
(1)None
(2)Custom Location
(3)Apple
(4)City Bicycle Ride
(5)City Run
(6)Freeway Drive
单机"Custom Location"选项,会弹出如下对话框,要求设置待模拟的经纬度
设置后,会触发 “-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray
locations = (
"<+26.06400300, +119.3107300> +/- 5.00m (speed -1.00 mps / course -1.00) @ 7/1/16, 4:05:32 PM China Standard Time"
)
注意:如果设置的不是 “Custom Location”,其他的选项我试了一遍,都会报错
触发 “-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error” 函数,打印如下
didFailWithError,error = Error Domain = kCLErrorDomainCode = 0 "(null)"
四、项目实战
(1)ViewController.h
//
// ViewController.h
// MapDemo
//
// Created by 555chy on 6/30/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import
//CoreLocation.framework
#import
//MapKit.framework
#import
//标注@protocol
#import "CustomAnnotation.h"
@interface ViewController : UIViewController
@end
(2)ViewController.m
//
// ViewController.m
// MapDemo
//
// Created by 555chy on 6/30/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property MKMapView *mapView;
@property CLLocationManager *locationManager;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self initLocationManager];
[self initMapView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - CLLocationManagerDelegate 获取当前位置
-(void)initLocationManager {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
/*
extern const CLLocationAccuracy kCLLocationAccuracyBestForNavigation __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
extern const CLLocationAccuracy kCLLocationAccuracyBest;
extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;
extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters;
extern const CLLocationAccuracy kCLLocationAccuracyKilometer;
extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers;
desired 渴望的、想得到的
accuracy 精确性、准确性
*/
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
/*
* distanceFilter
* Discussion: 讨论、谈论、详述、论述
* Specifies the minimum update distance in meters. Client will not be notified of movements of less
* than the stated value, unless the accuracy has improved. Pass in kCLDistanceFilterNone to be
* notified of all movements. By default, kCLDistanceFilterNone is used.
*/
//locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.distanceFilter = 1000.0f;
}
/*
This method is deprecated. If locationManager:didUpdateLocations: is implemented, this method will not be called.
当位置变化超过distanceFilter时,会调用该方法(该方法已被废弃,将不会触发该方法)
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(@"didUpdateToLocation, newLocation = %@, oldLocation = %@", newLocation, oldLocation);
}
/*
chronological 按时间的前后循序排列的、编年的
locations is an array of CLLocation objects in chronological order.
当位置变化超过distanceFilter时,会调用该方法
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
NSLog(@"didUpdateLocations, locations = %@", locations);
}
//如果地图查询错误,则会调用下面的协议函数
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(@"didFailWithError, error = %@", error);
}
/*
没有该函数时,运行MKMapView报错
Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
除了实现该函数,还要在Info.plist中添加
NSLocationAlwaysUsageDescription String 任意的描述语
NSLocationWhenInUseUsageDescription String 任意的描述语
Discussion: Invoked when the authorization status changes for this application.
*/
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
/*
typedef NS_ENUM(int, CLAuthorizationStatus) {
// User has not yet made a choice with regards to this application
kCLAuthorizationStatusNotDetermined = 0,
// This application is not authorized to use location services. Due
// to active restrictions on location services, the user cannot change
// this status, and may not have personally denied authorization
kCLAuthorizationStatusRestricted,
// User has explicitly denied authorization for this application, or
// location services are disabled in Settings.
kCLAuthorizationStatusDenied,
// User has granted authorization to use their location at any time,
// including monitoring for regions, visits, or significant location changes.
kCLAuthorizationStatusAuthorizedAlways NS_ENUM_AVAILABLE(NA, 8_0),
// User has granted authorization to use their location only when your app
// is visible to them (it will be made visible to them if you continue to
// receive location updates while in the background). Authorization to use
// launch APIs has not been granted.
kCLAuthorizationStatusAuthorizedWhenInUse NS_ENUM_AVAILABLE(NA, 8_0),
// This value is deprecated, but was equivalent to the new -Always value.
kCLAuthorizationStatusAuthorized NS_ENUM_DEPRECATED(10_6, NA, 2_0, 8_0, "Use kCLAuthorizationStatusAuthorizedAlways") __WATCHOS_PROHIBITED = kCLAuthorizationStatusAuthorizedAlways
};
*/
switch (status) {
case kCLAuthorizationStatusAuthorizedAlways:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusAuthorizedAlways");
[self.locationManager startUpdatingLocation];
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusAuthorizedWhenInUse");
[self.locationManager startUpdatingLocation];
break;
case kCLAuthorizationStatusDenied:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusDenied");
break;
case kCLAuthorizationStatusNotDetermined:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusNotDetermined");
if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
//应用在前台的时候可以搜到更新的位置信息
[self.locationManager requestWhenInUseAuthorization];
//应用在前台和后台(suspend或terminated)都可以获取到更新的位置数据信息
//[self.locationManager requestAlwaysAuthorization];
[self.locationManager startUpdatingLocation];
}
break;
case kCLAuthorizationStatusRestricted:
NSLog(@"didChangeAuthorizationStatus, status = %d(%@)", status, @"kCLAuthorizationStatusRestricted");
break;
default:
break;
}
}
#pragma mark - initMapView 初始化地图控件
-(void)initMapView {
self.mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
self.mapView.zoomEnabled = true;
self.mapView.scrollEnabled = true;
self.mapView.showsBuildings = true;
//显示罗盘
self.mapView.showsCompass = true;
self.mapView.showsScale = true;
self.mapView.showsTraffic = true;
self.mapView.showsUserLocation = true;
[self.mapView setDelegate:self];
[self.view addSubview:self.mapView];
/*
2d坐标
我这里用的是 中国福建省福州市工人文化宫的坐标
北纬N26.03‘39“ 东经E119.17‘57“
*/
CLLocationCoordinate2D coordinate;
//纬度
coordinate.latitude = 26.064003;
//经度
coordinate.longitude = 119.310730;
//设置地图显示范围
MKCoordinateSpan coordinateSpan;
//(0, 180]
coordinateSpan.latitudeDelta = 0.01;
//(0, 360]
coordinateSpan.longitudeDelta = 0.01;
//设置地图中心
MKCoordinateRegion coordinateRegion;
coordinateRegion.center = coordinate;
coordinateRegion.span = coordinateSpan;
//MKCoordinateRegionMake(<#CLLocationCoordinate2D centerCoordinate#>, <#MKCoordinateSpan span#>)
/*
hybrid 杂种的、混合的
satellite 卫星
flyover 立交桥、高架公路
typedef NS_ENUM(NSUInteger, MKMapType) {
MKMapTypeStandard = 0,
MKMapTypeSatellite,
MKMapTypeHybrid,
MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0),
MKMapTypeHybridFlyover NS_ENUM_AVAILABLE(10_11, 9_0),
} NS_ENUM_AVAILABLE(10_9, 3_0) __WATCHOS_PROHIBITED;
*/
[self.mapView setMapType:MKMapTypeStandard];
[self.mapView setRegion:coordinateRegion animated:YES];
//在中心点创建标记
[self createAnnotationWithCoordinate:coordinate];
//获取地图中心的地理位置描述
[self initGeocoderWithCoordinate:coordinate];
}
#pragma mark - MKAnnotation 在相应的坐标点创建标记
-(void)createAnnotationWithCoordinate:(CLLocationCoordinate2D) coordinate {
CustomAnnotation *annotation = [[CustomAnnotation alloc] initWithCoordinate:coordinate];
[self.mapView addAnnotation:annotation];
}
#pragma mark - CLGeocoder 将经纬坐标编码对象转化为地理信息的描述对象
-(void)initGeocoderWithCoordinate:(CLLocationCoordinate2D) coordinate {
//MKReverseGeocoder is now deprecated. Use CLGeocoder in CoreLocation instead.
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
//[NSDate date] 是获取当前时间
CLLocation *location = [[CLLocation alloc] initWithCoordinate:coordinate altitude:kCLDistanceFilterNone horizontalAccuracy:kCLLocationAccuracyBest verticalAccuracy:kCLLocationAccuracyBest timestamp:[NSDate date]];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) {
//NSLog(@"reverseGeocodeLocation completionHandler, placemarks = %@, error = %@ ", placemarks, error);
if(error == nil && placemarks.count > 0) {
for(int i=0;i *areasOfInterest; // eg. Golden Gate Park
thorough 彻底的、全面的、充分的、详尽的
thorough 通行、大道、大街
*/
NSLog(@"reverseGeocodeLocation placemark, locality = %@,%@, thoroughfare = %@,%@, name = %@", placemark.locality, placemark.subLocality, placemark.thoroughfare, placemark.subThoroughfare, placemark.name);
}
}
}];
}
@end
(3)CustomAnnotation.h
//
// CustomAnnotation.h
// MapDemo
//
// Created by 555chy on 7/1/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import
#import
//大头针标注
@interface CustomAnnotation : NSObject
@property CLLocationCoordinate2D coordinate;
@property NSString *title;
@property NSString *subtitle;
-(id)initWithCoordinate:(CLLocationCoordinate2D)coordinate;
@end
(4)CustomAnnotation.m
//
// CustomAnnotation.m
// MapDemo
//
// Created by 555chy on 7/1/16.
// Copyright © 2016 555chy. All rights reserved.
//
#import "CustomAnnotation.h"
@implementation CustomAnnotation
-(id)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
if(self = [super init]) {
self.coordinate = coordinate;
self.title = @"标题";
self.subtitle = @"子标题";
}
return self;
}
@end
五、运行截图