定位基础及权限详解
Core Location框架为定位用户当前位置和方向(Heading)提供支持。负责从设备硬件收集信息并以异步方式报告给应用程序。
- 定位方式:Wifi、蜂窝式移动电话基站、GPS卫星
- 定位优先级:GPS、Wifi、蜂窝式移动电话基站
- 定位准确性:GPS卫星(准确性高,但局限性大,比较耗费设备电量)、Wifi及蜂窝式移动电话基站(Wifi依赖网络,蜂窝取决于基站密度,耗费流量)
- iOS开发中,不能指定使用哪种方式进行定位,iOS系统会根据设备情况和周围环境,采用一套最佳的定位解决方案。
- iOS设备通过定位来确定用户位置信息,因为涉及用户隐私问题,所以在用户使用地图定位功能之前会与用户之间有交互行为。
- 服务过程:用户进行定位授权,同意则进行定位操作,反之提示用户无授权无法进行定位操作。
通过CoreLocation实现定位功能
定位权限申请
在info.plist文件里设置以下属性,对应的string值将会显示在弹出的对话框
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
定位权限
if([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
[_locationManager requestWhenInUseAuthorization];
[_locationManager requestAlwaysAuthorization];
}
位置管理器CLLocationManager
ViewController
@interface ViewController () <CLLocationManagerDelegate,MKMapViewDelegate>
@property (nonatomic, strong) MKMapView * mapView;
@property (nonatomic, strong) CLLocationManager * locationManager;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
[_mapView setDelegate:self];
//允许显示用户位置
[_mapView setShowsUserLocation:YES];
[_mapView setMapType:MKMapTypeStandard];
[self.view addSubview:_mapView];
//检测定位功能是否开启
if([CLLocationManager locationServicesEnabled]){
if(!_locationManager){
_locationManager = [[CLLocationManager alloc] init];
//定位权限
if([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
[_locationManager requestWhenInUseAuthorization];
[_locationManager requestAlwaysAuthorization];
}
//设置代理
[_locationManager setDelegate:self];
//设置定位精度
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
//设置距离筛选
[_locationManager setDistanceFilter:100];
//开始定位
[_locationManager startUpdatingLocation];
//设置开始识别方向
//[_locationManager startUpdatingHeading];
}
}else{
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:nil
message:@"您没有开启定位功能"
delegate:nil
cancelButtonTitle:@"确定"
otherButtonTitles:nil, nil];
[alertView show];
}
}
CLLocationManagerDelegate
授权状态发生改变的时候执行
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
switch(status){
case kCLAuthorizationStatusDenied:
{
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:nil
message:@"定位功能没有开启" delegate:nil
cancelButtonTitle:@"确定" otherButtonTitles:nil,nil];
[alertView show];
}
break;
default:
break;
}
}
定位成功以后调用
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
//[_locationManager stopUpdatingLocation];
CLLocation * location = locations.lastObject;
MKCoordinateRegion coordinateRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude), MKCoordinateSpanMake(0.1, 0.1));
[_mapView setRegion:[_mapView regionThatFits:coordinateRegion] animated:YES];
//[self reverseGeocoder:location];
}
定位失败
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(@"error:%@",error);
}
CLGeocoder
地理编码 - 地址转经纬度
CLGeocoder * geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:str completionHandler:^(NSArray *placemarks, NSError *error) {
if(error || placemarks.count == 0){
NSLog(@"error");
}else{
CLPlacemark * placemark = placemarks.firstObject;
//设置显示区域
MKCoordinateRegion coordinateRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(placemark.location.coordinate.latitude, placemark.location.coordinate.longitude), MKCoordinateSpanMake(0.1, 0.1));
[_mapView setRegion:[_mapView regionThatFits:coordinateRegion] animated:YES];
//设置标注
MKPointAnnotation * pointAnnotation = [[MKPointAnnotation alloc] init];
[pointAnnotation setTitle:placemark.name];
[pointAnnotation setCoordinate:CLLocationCoordinate2DMake(placemark.location.coordinate.latitude, placemark.location.coordinate.longitude)];
[_mapView addAnnotation:pointAnnotation];
}
}];
反地理编码 - 经纬度转地址
CLGeocoder * geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if(error || placemarks.count == 0){
NSLog(@"error");
}else{
CLPlacemark * placemark = placemarks.firstObject;
//设置标注
MKPointAnnotation * pointAnnotation = [[MKPointAnnotation alloc] init];
[pointAnnotation setTitle:placemark.name];
[pointAnnotation setCoordinate:CLLocationCoordinate2DMake(placemark.location.coordinate.latitude, placemark.location.coordinate.longitude)];
[_mapView addAnnotation:pointAnnotation];
//设置显示区域
MKCoordinateRegion coordinateRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(placemark.location.coordinate.latitude, placemark.location.coordinate.longitude), MKCoordinateSpanMake(0.1, 0.1));
[_mapView setRegion:[_mapView regionThatFits:coordinateRegion] animated:YES];
NSLog(@"placemark:%@",[[placemark addressDictionary] objectForKey:@"City"]);
}
}];
CLPlacemark存储地址信息
NSLog(@"placemark:%@",[[placemark addressDictionary] objectForKey:@"City"]);
屏幕触摸实现地理位置选择
长按设置坐标点
UILongPressGestureRecognizer * longpressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];
[_mapView addGestureRecognizer:longpressGestureRecognizer];
- (void)longPressed:(UILongPressGestureRecognizer *)recognizer {
if(recognizer.state == UIGestureRecognizerStateBegan){
CGPoint point = [recognizer locationInView:_mapView];
CLLocationCoordinate2D coordinate2D = [_mapView convertPoint:point toCoordinateFromView:_mapView];
[_mapView removeAnnotations:_mapView.annotations];
CLLocation * location = [[CLLocation alloc] initWithLatitude:coordinate2D.latitude longitude:coordinate2D.longitude];
[self reverseGeocoder:location];
}
}
获取地图界面点
CGPoint point = [recognizer locationInView:_mapView];
CLLocationCoordinate2D coordinate2D = [_mapView convertPoint:point toCoordinateFromView:_mapView];
移除原有的标注
[_mapView removeAnnotations:_mapView.annotations];
自定义标注
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
static NSString * key = @"key";
MKPinAnnotationView * pinAnnotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:key];
if(pinAnnotationView == nil){
pinAnnotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:key];
[pinAnnotationView setCanShowCallout:YES];
}
if([annotation isKindOfClass:[MKUserLocation class]]){
[pinAnnotationView setPinColor:MKPinAnnotationColorRed];
[((MKUserLocation *)annotation) setTitle:_titleString];
}else{
[pinAnnotationView setPinColor:MKPinAnnotationColorPurple];
}
return pinAnnotationView;
}
默认的是个蓝色闪烁点,如果自定义的话,就是插个大头针
[_mapView setShowsUserLocation:YES];
CoreLocation相关功能补充
CLHeading介绍
//设置开始识别方向
[_locationManager startUpdatingHeading];
位置更新
//定位成功以后就停止位置更新
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
......
[_locationManager stopUpdatingLocation];
}
其他
文本框键盘退出
[_textField resignFirstResponder];
文本框输入的判断
if([_textField.text length] == 0){
return;
}