美文网首页iOS
iOS - 使用系统地图进行导航

iOS - 使用系统地图进行导航

作者: 郭小弟 | 来源:发表于2016-08-03 14:13 被阅读1017次

    由于项目中少部分用到定位导航功能,就学习了一下这方面的知识,有自己总结的,也有从大神那里学习到的,有错误的地方希望有大神可以帮我提出,立即改正,写这篇文章的目的主要是想自己做个笔记,省的以后再做的时候耽误时间

    整体思路:在视图即将显示的时候实例化LocationManger对象,设置代理,在代理方法中获取到用户的经纬度,然后反地理编码,把经纬度转化成文字,赋值给cityStr,设置导航

    模拟器使用时需手动设置经纬度,也有可能设置好了,运行项目也不会执行,所以建议使用真机测试

    ![43568E90-BBCB-4B2E-A73A-15618058F8AD.png](https://img.haomeiwen.com/i1707826/67d3ce658f2fe9b7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    CLLocation 常用属性简介

      CLLocationDegrees latitude;纬度
      CLLocationDegrees longitude;经度
      @property(readonly, nonatomic) CLLocationCoordinate2D coordinate; 坐标,只有x.y
      @property(readonly, nonatomic) CLLocationDistance altitude;海拔
      @property(readonly, nonatomic) CLLocationAccuracy horizontalAccuracy;水平经度
      @property(readonly, nonatomic) CLLocationAccuracy verticalAccuracy;垂直经度
    

    版本支持

    判断版本,如果大于iOS8需要进行授权 ,同时配置plist文件

    ![Uploading C0002AE7-960C-4E3A-B2A6-F7A30C1DCBAD_053280.png . . .]

    NSLocationWhenInUseUsageDescription
    NSLocationAlwaysUsageDescription
    这两个key

    CLLocationManagerDelegate 说明

     //定位更新;从oldLocation到了newLocation;方法过期,如果实现了locationManager:didUpdateLocations:,该方法不被调用
    -(void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    //成功获取定位数据后就会激发该方法;locations最后一个为最新的
     -(void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray<CLLocation *> *)locations
    
     //成功获取设备方向数据后就会激发该方法
    -(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
     //是否显示方向刻度
     -(BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager
      //区域监听时,进入监听区域
     -(void)locationManager:(CLLocationManager *)manager
    didEnterRegion:(CLRegion *)region
      //区域监听时,离开监听区域
     -(void)locationManager:(CLLocationManager *)manager
    didExitRegion:(CLRegion *)region
    
    //定位失败时
    - (void)locationManager:(CLLocationManager *)manager
    didFailWithError:(NSError *)error;
    
    //监听区域失败
    - (void)locationManager:(CLLocationManager *)manager
    monitoringDidFailForRegion:(nullable CLRegion *)region
    withError:(NSError *)error
    //授权状态发生改变
    - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
    //已经开始监听区域
    - (void)locationManager:(CLLocationManager *)manager
    didStartMonitoringForRegion:(CLRegion *)region
    //暂停了定位数据获取
    - (void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager
    //恢复了定位数据的获取
    - (void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager
     //结束延迟定位更新时
     - (void)locationManager:(CLLocationManager *)manager
    didFinishDeferredUpdatesWithError:(nullable NSError *)error
    
     //计入观光区域
     - (void)locationManager:(CLLocationManager *)manager didVisit:(CLVisit *)visit 
    

    实际应用(使用系统的导航)

      - (void)viewWillAppear:(BOOL)animated{
         [super viewWillAppear:animated];
      //1. 创建位置管理器
      self.locationManager = [CLLocationManager new];
     //2>判断版本,如果大于iOS8需要进行授权 ,同时配置plist文件
     //用户使用时授权 大部分的应用应该使用此种授权方式
     // 判断可以使用宏定义(获取系统版本号)  / respondsToSelector
     if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
          //使用时授权
          [self.locationManager requestWhenInUseAuthorization];
         // 一直授权
         //[locationManager requestAlwaysAuthorization];
      }
        //3. 设置代理, 来获取数据
        self.locationManager.delegate = self;
    
      //4. 开始定位
      // 开始定位不要忘记停止定位  //[self.locationManager stopUpdatingLocation]
    
      [self.locationManager startUpdatingLocation];
    
     // 为了实现省电目的,对定位进行优化
    
     //5. 距离筛选器 (当用户发生一定位置的改变时, 再去调用代理方法, 以此实现省电)
     // 值: 多少米  譬如:设置10, 就代表用户位置发生10米以上的偏移时, 才去定位
      self.locationManager.distanceFilter = 10;
    
    //6. 设置精确度 (减少为卫星之间的计算, 以此实现省电)
    // 定位的方式: GPS 北斗 基站定位 WiFi 定位
    // iPhone打开定位: GPS 跟24颗卫星进行通讯
    //desired: 期望
    //Accurac: 精准度
    //extern const CLLocationAccuracy kCLLocationAccuracyBest;设备 使用电池供电时候,最高的精度
    //extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;精度10米
    //extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters;精度100米
    //extern const CLLocationAccuracy kCLLocationAccuracyKilometer;精度1000米
    //extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers;精度3000米
     //kCLLocationAccuracyBestForNavigation   导航情况下最高精度,一般要有外接电源时才 能使用
    
      self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
    }
    # pragma mark -懒加载 创建CLGeocoder对象
    -(CLGeocoder *)geo
    {
    if (!_geo)
    {
        _geo = [[CLGeocoder alloc] init];
    
    }
    return  _geo;
    }
    
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
    {
    //获取到经纬度
    CLLocation *location = locations.firstObject;
    
    //3. 调用方法即可
    [self.geo reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
    
        //3.1 防错处理
        if (placemarks.count == 0 || error) {
            NSLog(@"没有数据或数据解析出错");
            return;
        }
    
        //3.2 遍历数据
        for (CLPlacemark *pm in placemarks) {
    
            //3.3. 获取城市信息, 如果有城市信息就显示, 否则可以显示行政区域
            if (pm.name) {
    
                self.cityStr = pm.name;
            }else{
    
                self.cityStr = pm.locality;
            }
    
        }
    }];
    }
    
    //添加一个按钮,实现点击事件,
    -(IBAction)startNavigation:(id)sender
      {
      [self.geo  geocodeAddressString:self.cityStr completionHandler:^(NSArray *placemarks, NSError *error) {
       //获取到起点的MKplaceMark
        MKPlacemark *startPlace = [[MKPlacemark alloc] initWithPlacemark:[placemarks firstObject]];
    
        //等待获取到起点的placemarks之后在获取终点的placemarks,block回调延迟问题
        [self.geo  geocodeAddressString:@"北京市朝阳区东四环四方桥东南角" completionHandler:^(NSArray *placemarks, NSError *error) {
    
            /**
             获取到终点的MKplaceMark,MKPlaceMark 是ClPlaceMark的子类。
             */
            MKPlacemark *endPlace = [[MKPlacemark alloc] initWithPlacemark:[placemarks firstObject]];
    
            /**
             将MKPlaceMark转换成MKMapItem,这样可以放入到item这个数组中
    
             */
            MKMapItem *startItem = [[MKMapItem alloc ] initWithPlacemark:startPlace];
            MKMapItem *endItem = [[MKMapItem alloc ] initWithPlacemark:endPlace];
    
            NSArray *item = @[startItem ,endItem];
    
            //建立字典存储导航的相关参数
            NSMutableDictionary *md = [NSMutableDictionary dictionary];
            md[MKLaunchOptionsDirectionsModeKey] = MKLaunchOptionsDirectionsModeDriving;
            md[MKLaunchOptionsMapTypeKey] = [NSNumber numberWithInteger:MKMapTypeStandard];
    
            /**
             *调用app自带导航,需要传入一个数组和一个字典,数组中放入MKMapItem,
             字典中放入对应键值
    
             MKLaunchOptionsDirectionsModeKey   开启导航模式
             MKLaunchOptionsMapTypeKey  地图模式
             MKMapTypeStandard = 0,
             MKMapTypeSatellite,
             MKMapTypeHybrid
    
             // 导航模式
             MKLaunchOptionsDirectionsModeDriving 开车;
             MKLaunchOptionsDirectionsModeWalking 步行;
             */ #warning 其实所有的代码都是为了下面一句话,打开系统自带的高德地图然后执行某些动作,launchOptions里面的参数指定做哪些动作
            [MKMapItem openMapsWithItems:item launchOptions:md];
            }]; 
            }]
            }
    - (void)viewWillDisappear:(BOOL)animated
    {
    
      [super viewWillDisappear:animated];
    
      [self.locationManager stopUpdatingLocation];
    }

    相关文章

      网友评论

        本文标题:iOS - 使用系统地图进行导航

        本文链接:https://www.haomeiwen.com/subject/xapqsttx.html