美文网首页
展示MKMapView唤起内置导航功能

展示MKMapView唤起内置导航功能

作者: 羊妞麻麻 | 来源:发表于2018-09-06 14:04 被阅读42次

    需求如下:

    点击该页面地址或者点击定位地点唤醒地图类APP

    屏幕快照 2018-09-05 下午6.10.14.png

    地图上面显示的定位地点是从服务端获取的经纬度 比如CLLocationCoordinate2D location1 = CLLocationCoordinate2DMake(39.92, 116.3);

    思路:
    定义一个view,里面含有mapView相关功能,传入当前需要展示在地图上面的经纬度位置信息。

    代码块
    需要的框架
    CoreLocation.framework
    MapKit.framework

    .h

    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    
    @interface ZHMapManagerView : UIView
    
    @property(nonatomic,strong)NSArray *annotationPins;
    
    //设置目的地的经纬度 展示在地图上面
    - (void)setLatitudeAndLongitude:(CLLocationDegrees)latitude
                          longitude:(CLLocationDegrees)longitude;
    @end
    

    .m 首先需要导入#import <MapKit/MapKit.h>

    @interface ZHMapManagerView ()<MKMapViewDelegate,CLLocationManagerDelegate>
    //创建一个位置管理器
    @property (nonatomic, strong) CLLocationManager *locationManager;
    @property (nonatomic, strong) MKMapView *mapView;
    

    创建mapView

    @implementation ZHMapManagerView
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self createMapView];
        }
        return self;
    }
    
    - (void)createMapView
    {
        self.mapView = [[MKMapView alloc] initWithFrame:self.bounds];
        _mapView.delegate = self;
       //跟踪位置 设置map的跟踪模式
        _mapView.userTrackingMode = MKUserTrackingModeFollow;
       //不显示用户的当前位置
        _mapView.showsUserLocation = NO;
      // 地图类型效果
        _mapView.mapType = MKMapTypeStandard;
        [self addSubview:_mapView];
        
        self.locationManager = [[CLLocationManager alloc] init];
        WS(weakSelf)
     //请求用户授权
        [self openLocationServiceWithBlock:^(BOOL locationIsOpen) {
            if (!locationIsOpen) {
                [weakSelf.locationManager requestWhenInUseAuthorization];
            }
        }];
        
    }
    
    - (void)openLocationServiceWithBlock:(void(^)(BOOL locationIsOpen))returnBlock
    {
        if ([CLLocationManager locationServicesEnabled])
        {
            CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
            switch (status) {
                case kCLAuthorizationStatusNotDetermined:
                    NSLog(@"定位服务授权状态是:用户没有决定是否使用定位服务");
                    returnBlock(NO);
                    break;
                case kCLAuthorizationStatusRestricted:
                    returnBlock(NO);
                    NSLog(@"定位服务授权状态是受限制的");
                    break;
                case kCLAuthorizationStatusDenied:
                    
                    NSLog(@"定位服务授权状态已经被用户明确禁止,或者在设置里的定位服务中关闭");
                    break;
                case kCLAuthorizationStatusAuthorizedAlways:
                    returnBlock(YES);
                    NSLog(@"定位服务授权状态已经被用户允许在任何状态下获取位置信息");
                    break;
                case kCLAuthorizationStatusAuthorizedWhenInUse:
                    NSLog(@"定位服务授权状态仅被允许在使用应用程序的时候");
                    returnBlock(YES);
                    break;
                    
                default:
                    break;
            }
        }else
        {
            NSLog(@"定位服务不可用");
        }
        
    }
    

    注意事项

    需要在info.plist文件中增加这个 请求用户授权


    屏幕快照 2018-09-05 下午6.52.21.png

    iOS10 对隐私权限的管理
    比如访问的摄像头、麦克风等硬件,都需要提前请求应用权限、允许后才可以使用,或者现在要提前声明,虽然以往要求不严格。比如在iOS10中访问通讯录时,强制必须在Info.plist中加入NSContactsUsageDescription等描述,否则应用会崩溃。

    定位权限:Privacy - Location When In Use Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据

    定位权限: Privacy - Location Always Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据

    pragma mark - MKMapViewDelegate

    //自定义显示在地图上面大头针的图片样式 我只是改了图片
    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
    {
        if ([annotation isKindOfClass:[ZHMyAnnotation class]]) {
            
            static NSString *identifier = @"myAnnotation";
            MKAnnotationView *annotationView =[_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
            
            if (!annotationView) {
                annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
                annotationView.canShowCallout = NO;//能否显示大头针详情
                
            }
            annotationView.annotation = annotation;
            annotationView.image = ((ZHMyAnnotation *)annotation).image;
            return annotationView;
            
        } else {
            return nil;
        }
    }
    
    
    //点击大头针
    - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
        [self navigateTolatitude:30 longitude:116];
    }
    

    pragma mark - CLLocationManagerDelegate

    - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
        
        if (error) {
            NSLog(@"获取用户当前位置失败");
        }
    }
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
    {
        CLLocation *newLocation = locations[0];
        CLGeocoder *geocoder = [[CLGeocoder alloc] init];
        [geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *array, NSError *error){
            if (array.count > 0){
                CLPlacemark *placemark = [array objectAtIndex:0];
                
                CLLocationDegrees latitude=placemark.location.coordinate.latitude;
                CLLocationDegrees longitude=placemark.location.coordinate.longitude;
                
                NSString *city = [NSString stringWithFormat:@"%@%@",placemark.administrativeArea ? placemark.administrativeArea : @"",placemark.locality ? placemark.locality : @""];
                
                NSLog(@"adress---%@",[NSString stringWithFormat:@"%@ %@ %@ %@",placemark.country,city,placemark.name,placemark.thoroughfare]);
                
                NSLog(@"%@",[NSString stringWithFormat:@"经度:%.3f,纬度:%.3f",longitude,latitude]);
                
            }
            else if (error == nil && [array count] == 0)
            {
                NSLog(@"地图加载失败");
            }
            else if (error != nil)
            {
               NSLog(@"地图加载失败");
            }
        }];
        
        [manager stopUpdatingLocation];
        
    }
    

    地理编码和反地理编码都使用CLGeocoder类来实现.

    反地理编码

    使用reverseGeocodeLocation: completionHandler: 方法.将一个包含经纬度的CLLocation传进去,得到位置信息,就是反地理编码。

    在得到的CLPlacemark中取出name信息即可。如上代码⬆️

    地理编码

    使用 geocodeAddressString: completionHandler: 方法.将一个地名字符串转换为经纬度。

    在此方法中得到一个装着CLPlacemark的数组。一个CLPlacemark表示一个地理坐标,有位置信息(经纬度),以及地理位置的详情。将CLPlacemark中的经纬度取出,就完成了地理编码

    实现导航功能

    本次需求是唤起苹果内置的导航即可。地图导航所需的数据拿不到,交由苹果处理,在中国苹果交友高德地图处理。由于封装的比较好,我们本质上只需要一行代码:
    MKMapItem openMapsWithItems: launchOptions:

    代码块:

    - (void)navigateTolatitude:(CLLocationDegrees)latitude
                     longitude:(CLLocationDegrees)longitude
    {
        MKMapItem *currentLocation =[MKMapItem mapItemForCurrentLocation];
        MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) addressDictionary:nil]];
        
        [MKMapItem openMapsWithItems:@[currentLocation,toLocation] launchOptions:@{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,MKLaunchOptionsShowsTrafficKey:[NSNumber numberWithBool:YES]}];
    }
    

    1.首先获取地理编码目的地位置
    使用CLGeocoder进行地理编码,得到CLPlacemark, 转换CLPlacemark --> MKPlacemark
    MKPlacemark *mkPlacemark = [[MKPlacemark alloc] initWithPlacemark:placemark];

    2、获取当前位置和目的位置的mapItem
    //当前位置
    MKMapItem *currentLocation =[MKMapItem mapItemForCurrentLocation];

    //目的地位置
    MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) addressDictionary:nil]];

    3、开始导航
    第一个参数传入目的地和当前位置的数组,第二个是选项的字典。

    [MKMapItem openMapsWithItems:@[currentLocation,toLocation] launchOptions:@{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,MKLaunchOptionsShowsTrafficKey:[NSNumber numberWithBool:YES]}];

    //keys

    MKLaunchOptionsMapCenterKey:地图中心的坐标(NSValue)

    MKLaunchOptionsMapSpanKey:地图显示的范围(NSValue)

    MKLaunchOptionsShowsTrafficKey:是否显示交通信息(boolean NSNumber)

    //MKLaunchOptionsDirectionsModeKey: 导航类型(NSString)

    {

    MKLaunchOptionsDirectionsModeDriving:驾车

    MKLaunchOptionsDirectionsModeWalking:步行

    }

    //MKLaunchOptionsMapTypeKey:地图类型(NSNumber)

    enum {

    MKMapTypeStandard = 0,

    MKMapTypeSatellite,

    MKMapTypeHybrid

    };//MKLaunchOptionsCameraKey 3D地图效果

    以上是针对app内展示经纬度和导航去这里的基本代码。

    相关文章

      网友评论

          本文标题:展示MKMapView唤起内置导航功能

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