一、定位功能
CLLocationManager 定位的基础信息
CLLocation 某个位置的地理信息
CLLocationCoordinate2D 存放经纬度结构体
CLGeocoder 地理位置编码和反编码的类
CLPlacemark 地标
在info.plist中加一条,对在向用户请求开启定位时显示
定位
@property (nonatomic,retain)CLLocationManager *locationManager;//地图管理对象,所有的定位服务需要借助此对象来完成 - (void)viewDidLoad { [super viewDidLoad]; //初始化编码对象 self.geocoder = [[CLGeocoder alloc]init]; //初始化管理对象 self.locationManager = [[CLLocationManager alloc]init]; //判断是否允许定位 BOOL isPosition = [CLLocationManager locationServicesEnabled]; if (!isPosition) { NSLog(@"未开启定位"); } else//定位已经开启 { //取得授权,always 不管当前应用程序是否在前台运行,都可获得授权 [self.locationManager requestAlwaysAuthorization]; //设置定位的频率,多少米定位一次 self.locationManager.distanceFilter = 10; //定位精度,精度越高越费电 self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; //指定代理 self.locationManager.delegate = self; //开始更新定位信息 [self.locationManager startUpdatingLocation]; // } //调用编码方法, // [self geocoderWithPlaceString:@"Xi'an"]; CLLocation *location = [[CLLocation alloc]initWithLatitude:34.1 longitude:108.0]; //逆编码 // [self reverseGeocoderWithLoction:location]; }
定位的代理方法
#pragma mark -- 定位代理方法 //定位出错 -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"定位失败 -- %@",[error description]); } //实时获得位置信息,此代理方法会被多次执行 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations { //locations 数组存取所有定位过的位置,数组最后一个元素为最新的位置信息 if (locations.count) { //最新的位置信息,包含经纬度,行走速度 CLLocation *location = locations.lastObject; NSLog(@"纬度--%f,经度--%f,location--%@",location.coordinate.latitude,location.coordinate.longitude,location); //反地理编码:将location对象转换为具体的位置信息 [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { //CLPlacemark对象中存储着位置的具体信息 if (placemarks.count) { //取出数组最后一个元素 CLPlacemark *lastPlaceMark = placemarks.lastObject; NSLog(@"name -- %@,%@,%@,%@,%@,%@,%@",lastPlaceMark.name,lastPlaceMark.locality,lastPlaceMark.administrativeArea,lastPlaceMark.country,lastPlaceMark.subAdministrativeArea,lastPlaceMark.subLocality,lastPlaceMark.thoroughfare); } }]; } // CLLocation *location=placemark.location;//位置 // CLRegion *region=placemark.region;//区域 // NSDictionary *addressDic= placemark.addressDictionary;//详细地址信息字典,包含以下部分信息 // NSString *name=placemark.name;//地名 // NSString *thoroughfare=placemark.thoroughfare;//街道 // NSString *subThoroughfare=placemark.subThoroughfare; //街道相关信息,例如门牌等 // NSString *locality=placemark.locality; // 城市 // NSString *subLocality=placemark.subLocality; // 城市相关信息,例如标志性建筑 // NSString *administrativeArea=placemark.administrativeArea; // 州 // NSString *subAdministrativeArea=placemark.subAdministrativeArea; //其他行政区域信息 // NSString *postalCode=placemark.postalCode; //邮编 // NSString *ISOcountryCode=placemark.ISOcountryCode; //国家编码 // NSString *country=placemark.country; //国家 // NSString *inlandWater=placemark.inlandWater; //水源、湖泊 // NSString *ocean=placemark.ocean; // 海洋 // NSArray *areasOfInterest=placemark.areasOfInterest; //关联的或利益相关的地标 else { NSLog(@"无定位信息"); }} //已经废弃的方法 -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { NSLog(@"定位2");} //改变方向时触发 -(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { } //进入某个区域后执行 -(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{ } //走出某个区域后执行 -(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{ }
#pragma mark -- 地理编码和反编码 //地理编码,把城市名称转换为location -(CLPlacemark*)geocoderWithPlaceString:(NSString*)placeName { __block CLPlacemark *placeMark ; [self.geocoder geocodeAddressString:placeName completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { CLPlacemark *lastPlaceMark = placemarks.lastObject; NSLog(@"%@的 经度--%f ,纬度--%f",placeName,lastPlaceMark.location.coordinate.longitude, lastPlaceMark.location.coordinate.latitude); }]; return _myPlaceMark; } //地理反编码 -(CLPlacemark*)reverseGeocoderWithLoction:(CLLocation*)location { [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { CLPlacemark *lastPlaceMark = placemarks.lastObject; NSLog(@"反编码 %@ ,%@",lastPlaceMark.name,lastPlaceMark.addressDictionary); }]; return placeMark; }
二、地图
导入框架MapKit.framework(iOS5之后不再需要手动导入)
下面的代码就可以是地图显示出来
#import <MapKit/MapKit.h> @interface MapViewController ()<MKMapViewDelegate> @property (nonatomic,retain)MKMapView *mapView;//显示地图的控件 @end @implementation MapViewController //地图懒加载 -(MKMapView *)mapView { if (!_mapView) { _mapView = [[MKMapView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; [self.view addSubview:_mapView]; } return _mapView; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //创建地图对象 //地图类型 self.mapView.mapType = MKMapTypeStandard; //地图跟踪 _mapView.userTrackingMode = MKUserTrackingModeFollow; //设置地图代理 _mapView.delegate = self; //设置为可以显示用户位置: _mapView.showsUserLocation = YES; }
地图的一些常用方法
添加大头针
- (void)addAnnotation:(id <MKAnnotation>)annotation; - (void)addAnnotations:(NSArray<id<MKAnnotation>> *)annotations; - (void)removeAnnotation:(id <MKAnnotation>)annotation; - (void)removeAnnotations:(NSArray<id<MKAnnotation>> *)annotations;
- (void)addOverlay:(id <MKOverlay>)overlay level:(MKOverlayLevel)level NS_AVAILABLE(10_9, 7_0); - (void)addOverlays:(NSArray<id<MKOverlay>> *)overlays level:(MKOverlayLevel)level NS_AVAILABLE(10_9, 7_0); - (void)removeOverlay:(id <MKOverlay>)overlay NS_AVAILABLE(10_9, 4_0); - (void)removeOverlays:(NSArray<id<MKOverlay>> *)overlays NS_AVAILABLE(10_9, 4_0);
下面的代码可以在两个地点之间添加导航线路
- (void)setLine { #pragma mark -- 导航线路 NSString *add1=@"西安"; NSString *add2=@"北京"; //通过反编码得到两个地点的CLPlacemark //这个方法只能生效1个,所以不能分开写 self.geocoder = [[CLGeocoder alloc]init]; [self.geocoder geocodeAddressString:add1 completionHandler:^(NSArray *placemarks, NSError *error) { if (error) return; CLPlacemark *fromPm=[placemarks firstObject]; [self.geocoder geocodeAddressString:add2 completionHandler:^(NSArray *placemarks, NSError *error) { CLPlacemark *toPm=[placemarks firstObject]; [self addLineFrom:fromPm to:toPm]; }]; }]; } -(void)addLineFrom:(CLPlacemark *)fromPm to:(CLPlacemark *)toPm{ //添加2个大头针 MyAnnotation *anno0=[[MyAnnotation alloc]init]; anno0.coordinate=fromPm.location.coordinate; [self.mapView addAnnotation:anno0]; MyAnnotation *anno1=[[MyAnnotation alloc]init]; anno1.coordinate=toPm.location.coordinate; [self.mapView addAnnotation:anno1]; //设置方向请求 MKDirectionsRequest *request=[[MKDirectionsRequest alloc]init]; //设置起点终点 MKPlacemark *sourcePm=[[MKPlacemark alloc]initWithPlacemark:fromPm]; request.source=[[MKMapItem alloc]initWithPlacemark:sourcePm]; MKPlacemark *destiPm=[[MKPlacemark alloc]initWithPlacemark:toPm]; request.destination=[[MKMapItem alloc]initWithPlacemark:destiPm]; //定义方向对象 MKDirections *dirs=[[MKDirections alloc]initWithRequest:request]; //计算路线 [dirs calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) { NSLog(@"总共有%lu条线路",(unsigned long)response.routes.count); for (MKRoute *route in response.routes) { //划线 [self.mapView addOverlay:route.polyline]; } }]; }
//划线就是添加路径,就是添加遮盖 -(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{ MKPolylineRenderer *renderer=[[MKPolylineRenderer alloc]initWithOverlay:overlay]; renderer.strokeColor=[UIColor redColor]; return renderer; }
对大头针进行设置
这个使用了重用机制
//每出现一次大头针,都会调用一次 -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { //如果返回nil 就是系统默认样式 //判断类型 if([annotation isKindOfClass:[MyAnnotation class]]) { //从重用队列取出AnnotationView 如果存在直接使用,不存在就创建 MKAnnotationView *annView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"tationView"]; if (!annView) { //不存在,需要创建 annView = [[MKAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"tationView"]; } //设置一张图片 annView.image = [UIImage imageNamed:@"b2"]; annView.canShowCallout = YES; annView.calloutOffset = CGPointMake(20, 20); //赋值视图 UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 20, 20)]; view.backgroundColor = [UIColor redColor]; annView.leftCalloutAccessoryView = view; return annView; } else if ([annotation isKindOfClass:[MKPointAnnotation class]]) { //从重用队列取出AnnotationView 如果存在直接使用,不存在就创建 MKPinAnnotationView *annView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"pointView"]; if (!annView) { //不存在,需要创建 annView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"pointView"]; } annView.image = [UIImage imageNamed:@"b2"]; //是否显示标注 annView.canShowCallout = YES; //标准偏移的位置 annView.calloutOffset = CGPointMake(20, 20); //设置颜色,子类效果 annView.pinTintColor = [UIColor blueColor]; //设置从天而降的导航效果 annView.animatesDrop = YES; return annView; } return nil; }
效果
代理方法很多
常用的:
//检测用户当前位置 -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { //打印经纬度 NSLog(@"经度 -- %f,纬度 -- %f",userLocation.location.coordinate.longitude,userLocation.location.coordinate.latitude); } //定位失败 - (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error NS_AVAILABLE(10_9, 4_0);
//地区变化触发 - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated; - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated; //地图加载触发 - (void)mapViewWillStartLoadingMap:(MKMapView *)mapView; - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView; - (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error; //地图渲染触发 - (void)mapViewWillStartRenderingMap:(MKMapView *)mapView NS_AVAILABLE(10_9, 7_0); - (void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered
大头针的代理方法
//添加大头针后 - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views; //选择了大头针 - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(10_9, 4_0); //取消选择 - (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(10_9, 4_0);