OC-UI阶段学习40-定位和地图

一、定位功能


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;
}


效果

OC-UI阶段学习40-定位和地图_第1张图片


代理方法很多

常用的:

//检测用户当前位置
-(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);








你可能感兴趣的:(ios,oc,导航,地图,地理信息)