美文网首页MKMapKit
iOS-系统原生的地图和定位简单使用

iOS-系统原生的地图和定位简单使用

作者: 长衣貌 | 来源:发表于2018-09-15 14:59 被阅读0次

    iOS工程中简单使用原生的地图框架
    目  录:
    一、使用MKMap控件
    二、根据地址定位
    三、在地图上添加锚点
    四、导航

    iOS从3.0版本开始提供了MapKit.frameword支持。该框架提供了一个可被嵌入到应用程序中的地图视图类MKMapView,该地图视图类包含一个可上下、左右滚动的地图视图,而且可以非常方便地在地图中添加定制消息,并可以将其嵌入到应用程序中,通过编程的方式设置地图的各种属性(包含当前地图显示的区域以及用户当前所在位置)。
      iOS从4.0开始,MapKit框架支持可拖动标注和定制覆盖层。可拖动标注允许开发者以编程的方式或用户交互方式来重定位某个标注的位置;覆盖层则可用于创建有多个点组成的复杂标注,这种覆盖层可用于创建公交路线、公园边界或气象信息(如雷达数据)等。
      现在很多的社交软件都引入了地图和定位功能,要想实现这2大功能,那就不得不学习其中的2个框架:MaKit和CoreLocation
      (1)CoreLocation框架可以使用硬件设备来进行定位服务
      (2)MapKit框架能够使应用程序做一些地图展示与交互的相关功能
      iOS定位支持的3中模式:手机基站、WIFI、GPS
    首先需要倒入两个动态库.


    屏幕快照 2018-09-15 14.55.06.png

    一、使用MKMapView控件
      MKMapView控件中位于MapKit.framework中,因此为了在iOS应用中使用该控件,需要完成两件事情:1,为该应用添加MapKit框架;2,在使用MKMapView及相关类的源文件中使用“#import<MapKit/MapKit.h>”导入MapKit.framework的头文件。本章绝大部分示例都使用了MKMapView,因此都需要执行上面两步操作。

    #import "defind.h" ///< 通用宏
    #import <MapKit/MapKit.h>
    #import <CoreLocation/CoreLocation.h>
    

    定义全局的地图视图对象和定位对象

    /** 地图对象 */
    @property (nonatomic, strong) MKMapView * mapView;
    /** 定位管理者 */
    @property (nonatomic, strong) CLLocationManager * locationManager;
    

    懒加载全局的地图对象属性

    /** 懒加载地图视图 */
    - (MKMapView *)mapView{
        if (_mapView == nil) {
            _mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT - 100)];
            /** 设置地图类型 */
            _mapView.mapType = MKMapTypeStandard;
            //设置地图可缩放
            _mapView.zoomEnabled = YES;
            //设置地图可滚动
            _mapView.scrollEnabled = YES;
            //设置地图可旋转
            _mapView.rotateEnabled = YES;
            //设置显示用户显示位置
            _mapView.showsUserLocation = YES;
            //为MKMapView设置delegate
            _mapView.delegate = self;
        }
        return _mapView;
    }
    

    地图视图的常用属性和方法

    //区域是地图的坐标和跨度。
    //区域可以被修改,以适应视图的高宽比,使用Region:。
    @property (nonatomic) MKCoordinateRegion region;
    - (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated;
    
    // centerCoordinate允许在不更改缩放级别的情况下更改区域的坐标。
    @property (nonatomic) CLLocationCoordinate2D centerCoordinate;
    - (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated;
    
    //返回包含给定区域的地图视图的长宽比区域,具有相同的中心点。
    - (MKCoordinateRegion)regionThatFits:(MKCoordinateRegion)region;
    
    //进入投影坐标下的地图可见区域。
    @property (nonatomic) MKMapRect visibleMapRect;
    - (void)setVisibleMapRect:(MKMapRect)mapRect animated:(BOOL)animate;
    
    //返回修改后的MKMapRect,以适应映射的高宽比。
    - (MKMapRect)mapRectThatFits:(MKMapRect)mapRect;
    
    //边缘填充是在指定的MKMapRect周围两侧的最小填充。
    - (void)setVisibleMapRect:(MKMapRect)mapRect edgePadding:(UIEdgeInsets)insets animated:(BOOL)animate;
    - (MKMapRect)mapRectThatFits:(MKMapRect)mapRect edgePadding:(UIEdgeInsets)insets;
    
    //3D地图用到的属性
    @property (nonatomic, copy) MKMapCamera *camera NS_AVAILABLE(10_9, 7_0);
    - (void)setCamera:(MKMapCamera *)camera animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);
    
    //*********************下面是控制可用用户交互的类型
    
    //默认只启用缩放和滚动。
    @property (nonatomic, getter=isZoomEnabled) BOOL zoomEnabled;
    @property (nonatomic, getter=isScrollEnabled) BOOL scrollEnabled;
    
    //在Mac OS X和iOS 7.0及更高版本上默认启用旋转和俯仰。
    @property (nonatomic, getter=isRotateEnabled) BOOL rotateEnabled NS_AVAILABLE(10_9, 7_0) __TVOS_PROHIBITED;
    @property (nonatomic, getter=isPitchEnabled) BOOL pitchEnabled NS_AVAILABLE(10_9, 7_0) __TVOS_PROHIBITED;
    
    //是否展示缩放控件
    @property (nonatomic) BOOL showsZoomControls NS_AVAILABLE(10_9, NA);
    
    //显示指南针
    @property (nonatomic) BOOL showsCompass NS_AVAILABLE(10_9, 9_0) __TVOS_PROHIBITED;
    
    //显示刻度比例
    @property (nonatomic) BOOL showsScale NS_AVAILABLE(10_10, 9_0);
    
    //显示兴趣点, 会影响地图的样式MKMapTypeStandard 和 MKMapTypeHybrid
    @property (nonatomic) BOOL showsPointsOfInterest NS_AVAILABLE(10_9, 7_0); 
    
    //显示建筑物
    @property (nonatomic) BOOL showsBuildings NS_AVAILABLE(10_9, 7_0); 
    
    //显示交通
    @property (nonatomic) BOOL showsTraffic NS_AVAILABLE(10_11, 9_0); 
    
    //显示用户位置, 设置为YES,将用户位置注释添加到映射并开始更新其位置
    @property (nonatomic) BOOL showsUserLocation;
    
    //表示用户位置的注释
    @property (nonatomic, readonly) MKUserLocation *userLocation;
    
    //用户跟踪模式。跟随用户的移动
    @property (nonatomic) MKUserTrackingMode userTrackingMode NS_AVAILABLE(NA, 5_0);
    - (void)setUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated NS_AVAILABLE(NA, 5_0);
    
    //如果用户的位置显示在当前可见的地图区域内,则返回YES。
    @property (nonatomic, readonly, getter=isUserLocationVisible) BOOL userLocationVisible;
    
    //注释是用于在地图上标注坐标的模型。   定位锚点的显示信息, 后面有使用介绍..
    //实现mapView:viewForAnnotation:在MKMapViewDelegate上返回每个注释的注释视图。
    //添加锚点
    - (void)addAnnotation:(id <MKAnnotation>)annotation;
    - (void)addAnnotations:(NSArray<id<MKAnnotation>> *)annotations;
    
    //移除锚点
    - (void)removeAnnotation:(id <MKAnnotation>)annotation;
    - (void)removeAnnotations:(NSArray<id<MKAnnotation>> *)annotations;
    
    //当前地图视图中的锚点数组, 用来获取当前地图视图中的所有锚点
    @property (nonatomic, readonly) NSArray<id<MKAnnotation>> *annotations;
    - (NSSet<id<MKAnnotation>> *)annotationsInMapRect:(MKMapRect)mapRect NS_AVAILABLE(10_9, 4_2);
    
    //当前显示的注释视图;如果未显示注释的视图,则返回nil。
    - (nullable MKAnnotationView *)viewForAnnotation:(id <MKAnnotation>)annotation;
    
    //委托用于获取可重用注释视图,或为已注册的类创建新视图,而不是分配新视图。在重用池内找可以重用的视图,(相同的标识符)
    - (nullable MKAnnotationView *)dequeueReusableAnnotationViewWithIdentifier:(NSString *)identifier;
    
    //委托用于获取可重用注释视图,或为已注册的类创建新视图,而不是分配新视图。如果无法获得视图,则抛出异常。
    - (MKAnnotationView *)dequeueReusableAnnotationViewWithIdentifier:(NSString *)identifier forAnnotation:(id<MKAnnotation>)annotation;
    
    //注册一个MKAnnotationView子类,当dequeueReusableAnnotationViewWithIdentifier:没有要重用的视图时实例化。
    - (void)registerClass:(nullable Class)viewClass forAnnotationViewWithReuseIdentifier:(NSString *)identifier NS_AVAILABLE(10_13, 11_0) __TVOS_AVAILABLE(11_0);
    
    //选择或取消选择给定的注释。如果需要,请委托获取相应的注释视图。
    - (void)selectAnnotation:(id <MKAnnotation>)annotation animated:(BOOL)animated;
    - (void)deselectAnnotation:(nullable id <MKAnnotation>)annotation animated:(BOOL)animated;
    @property (nonatomic, copy) NSArray<id<MKAnnotation>> *selectedAnnotations;
    
    // annotationvisibl是当前显示注释视图的可见rect。
    //在mapView:didAddAnnotationViews中动画添加注释视图时,委托可以使用annotationvisibl:
    @property (nonatomic, readonly) CGRect annotationVisibleRect;
    
    //定位映射,使所提供的注释数组在最大程度上都是可见的。
    - (void)showAnnotations:(NSArray<id<MKAnnotation>> *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);
    
    //覆盖枚举
    typedef NS_ENUM(NSInteger, MKOverlayLevel) {
        MKOverlayLevelAboveRoads = 0,//注意标签包括盾牌和兴趣点图标。
        MKOverlayLevelAboveLabels
    } NS_ENUM_AVAILABLE(10_9, 7_0) __TVOS_AVAILABLE(9_2) __WATCHOS_PROHIBITED;
    

    MKMapView的类别(OverlaysAPI)

    //覆盖是用来表示要绘制在地图顶部的区域的模型。
    //这与注释相反,注释表示地图上的点。
    //实现mapview:rendererForOverlay:在MKMapViewDelegate上为每个覆盖返回渲染器。
    //添加覆盖
    - (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)insertOverlay:(id <MKOverlay>)overlay atIndex:(NSUInteger)index level:(MKOverlayLevel)level NS_AVAILABLE(10_9, 7_0);
    
    - (void)insertOverlay:(id <MKOverlay>)overlay aboveOverlay:(id <MKOverlay>)sibling NS_AVAILABLE(10_9, 4_0);
    - (void)insertOverlay:(id <MKOverlay>)overlay belowOverlay:(id <MKOverlay>)sibling NS_AVAILABLE(10_9, 4_0);
    
    //交换覆盖
    - (void)exchangeOverlay:(id <MKOverlay>)overlay1 withOverlay:(id <MKOverlay>)overlay2 NS_AVAILABLE(10_9, 7_0);
    
    //获取视图上的覆盖
    @property (nonatomic, readonly) NSArray<id<MKOverlay>> *overlays NS_AVAILABLE(10_9, 4_0);
    - (NSArray<id<MKOverlay>> *)overlaysInLevel:(MKOverlayLevel)level NS_AVAILABLE(10_9, 7_0);
    
    //获取当前覆盖渲染器;如果没有显示覆盖层,返回nil。
    - (nullable MKOverlayRenderer *)rendererForOverlay:(id <MKOverlay>)overlay NS_AVAILABLE(10_9, 7_0);
    
    //当前显示的覆盖视图;如果尚未创建视图,则返回nil。
    //最好使用MKOverlayRenderer和-rendererForOverlay。
    - (MKOverlayView *)viewForOverlay:(id <MKOverlay>)overlay NS_DEPRECATED_IOS(4_0, 7_0) __TVOS_PROHIBITED;
    
    //这些方法隐式地操作MKOverlayLevelAboveLabels中的覆盖,在将来的版本中可能会反对使用指定级别的方法。
    - (void)addOverlay:(id <MKOverlay>)overlay NS_AVAILABLE(10_9, 4_0);
    - (void)addOverlays:(NSArray<id<MKOverlay>> *)overlays NS_AVAILABLE(10_9, 4_0);
    
    - (void)insertOverlay:(id <MKOverlay>)overlay atIndex:(NSUInteger)index NS_AVAILABLE(10_9, 4_0);
    - (void)exchangeOverlayAtIndex:(NSUInteger)index1 withOverlayAtIndex:(NSUInteger)index2 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;
    
    //地图视图加载地图失败 error错误信息
    - (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error;
    
    //地图视图将开始绘制地图
    - (void)mapViewWillStartRenderingMap:(MKMapView *)mapView NS_AVAILABLE(10_9, 7_0);
    
    //地图视图已经完成绘制地图, 
    - (void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered NS_AVAILABLE(10_9, 7_0);
    
    // mapView:viewForAnnotation:为每个注释提供视图。
    //可以对所有或部分添加的注释调用此方法。
    //对于MapKit提供了注释(例如。返回nil以使用MapKit提供的注释视图。
    - (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
    
    // mapView:didAddAnnotationViews:在在映射中添加和定位注释视图之后调用。
    //委托可以实现此方法来动画添加注释视图。
    //使用注释视图的当前位置作为动画的目的地。
    - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views;
    
    // mapView:annotationView:calloutAccessoryControlTapped:在用户点击左右标注附件uicontrol时调用
    - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control __TVOS_PROHIBITED;
    
    //选择注释视图
    - (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);
    
    //地图视图将开始定位用户位置
    - (void)mapViewWillStartLocatingUser:(MKMapView *)mapView NS_AVAILABLE(10_9, 4_0);
    
    //地图视图停止定位用户位置
    - (void)mapViewDidStopLocatingUser:(MKMapView *)mapView NS_AVAILABLE(10_9, 4_0);
    
    //用户的位置更新回调
    - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation NS_AVAILABLE(10_9, 4_0);
    
    //有错误 定位用户失败
    - (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error NS_AVAILABLE(10_9, 4_0);
    
    //拖动后的回调, newState:新的状态, oldState:旧的状态
    - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState 
       fromOldState:(MKAnnotationViewDragState)oldState NS_AVAILABLE(10_9, 4_0) __TVOS_PROHIBITED;
    
    //用户的跟踪模式发生改变回调
    - (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated NS_AVAILABLE(NA, 5_0);
    
    //覆盖的渲染器
    - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay NS_AVAILABLE(10_9, 7_0);
    
    //添加覆盖渲染完成回调
    - (void)mapView:(MKMapView *)mapView didAddOverlayRenderers:(NSArray<MKOverlayRenderer *> *)renderers NS_AVAILABLE(10_9, 7_0);
    
    //设置覆盖的视图
    - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay NS_DEPRECATED_IOS(4_0, 7_0) __TVOS_PROHIBITED;
    
    //设置覆盖视图完成回调
    - (void)mapView:(MKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews NS_DEPRECATED_IOS(4_0, 7_0) __TVOS_PROHIBITED;
    
    //返回默认MKClusterAnnotation的nil,返回一个不包含给定成员注释数组的集群注释是不可以的。
    - (MKClusterAnnotation *)mapView:(MKMapView *)mapView clusterAnnotationForMemberAnnotations:(NSArray<id<MKAnnotation>>*)memberAnnotations NS_AVAILABLE(10_13, 11_0) __TVOS_AVAILABLE(11_0) __WATCHOS_PROHIBITED;
    

    懒加载全局的定位对象

    - (CLLocationManager *)locationManager{
        if (_locationManager == nil) {
            _locationManager = [[CLLocationManager alloc] init];
            /** 导航类型 */
            _locationManager.activityType = CLActivityTypeFitness;
            /** 设置代理, 非常关键 */
            _locationManager.delegate = self;
            /** 想要定位的精确度, kCLLocationAccuracyBest:最好的 */
            _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
            /** 获取用户的版本号 */
            if([[UIDevice currentDevice].systemVersion floatValue] >= 8.0){
                [_locationManager requestAlwaysAuthorization];
            }
            /** 允许后台获取用户位置(iOS9.0) */
            if([[UIDevice currentDevice].systemVersion floatValue] >= 9.0){
                // 一定要勾选后台模式 location updates 否者程序奔溃
                _locationManager.allowsBackgroundLocationUpdates = YES;
            }
        }
        return _locationManager;
    }
    

    CLLocationManager的常用属性和方法

    //设备定位枚举 ,  指定物理设备方向,相当于UIDeviceOrientation。
    typedef NS_ENUM(int, CLDeviceOrientation) {
        CLDeviceOrientationUnknown = 0,
        CLDeviceOrientationPortrait,
        CLDeviceOrientationPortraitUpsideDown,
        CLDeviceOrientationLandscapeLeft,
        CLDeviceOrientationLandscapeRight,
        CLDeviceOrientationFaceUp,
        CLDeviceOrientationFaceDown
    };
    
    // 表示应用程序的当前授权状态的枚举
    typedef NS_ENUM(int, CLAuthorizationStatus) {
        //用户还没有对这个应用程序做出选择
        kCLAuthorizationStatusNotDetermined = 0,
    
        //本应用程序未被授权使用位置服务。由于要对位置服务进行主动限制,用户不能更改此状态,并可能没有亲自拒绝授权
        kCLAuthorizationStatusRestricted,
    
        //用户已明确拒绝此应用程序的授权,或在设置中禁用位置服务。
        kCLAuthorizationStatusDenied,
    
        //用户已授权在任何时候使用其位置,包括对区域、访问或重大地点变化的监测。
            //这个值应该在iOS、tvOS和watchOS上使用。可于MacOS,但kCLAuthorizationStatusAuthorized是同义词和首选。
        kCLAuthorizationStatusAuthorizedAlways NS_ENUM_AVAILABLE(10_12, 8_0),
    
        //用户仅在您的应用程序中授权使用其位置对他们是可见的(如果你继续这样做,他们就会看到在后台接收位置更新)。授权使用尚未授予启动api。
            //这个值在MacOS上不可用。它应该在iOS, tvOS和watchOS上使用
        kCLAuthorizationStatusAuthorizedWhenInUse NS_ENUM_AVAILABLE(NA, 8_0),
    
        //用户已授权此应用程序使用位置服务。
            //这个值在iOS、tvOS和watchOS上是不赞成或禁止的。它应该用在MacOS上。
        kCLAuthorizationStatusAuthorized NS_ENUM_DEPRECATED(10_6, NA, 2_0, 8_0, "Use kCLAuthorizationStatusAuthorizedAlways") __TVOS_PROHIBITED __WATCHOS_PROHIBITED = kCLAuthorizationStatusAuthorizedAlways
    };
    
    //列举不同的活动类型。这个目前影响确定何时位置更新,可能自动暂停位置更新。
    typedef NS_ENUM(NSInteger, CLActivityType) {
        CLActivityTypeOther = 1,
        CLActivityTypeAutomotiveNavigation, //用于汽车导航
        CLActivityTypeFitness,              //包括任何行人活动
        CLActivityTypeOtherNavigation       //其他导航情况(不包括行人导航),例如船只、火车或飞机的导航
    };
    
    //CLLocationManager对象是位置服务的入口点。
    id _internal;
    
    //确定用户是否启用了位置服务。
    //如果没有,并且您继续调用其他CoreLocation API,用户将收到警告对话框。
    //您可能希望检查此属性并仅在用户明确请求时使用位置服务。
    + (BOOL)locationServicesEnabled API_AVAILABLE(ios(4.0), macos(10.7));
    
    //如果设备支持标题服务,返回YES,否则返回NO。
    + (BOOL)headingAvailable API_AVAILABLE(ios(4.0), macos(10.7)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //如果设备支持重要的位置更改监视,返回YES,否则返回NO。
    + (BOOL)significantLocationChangeMonitoringAvailable API_AVAILABLE(ios(4.0), macos(10.7)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //确定设备是否支持对指定类型区域的监视。
    //如果没有,所有监视指定区域类型的尝试都将失败。
    + (BOOL)isMonitoringAvailableForClass:(Class)regionClass API_AVAILABLE(ios(7.0), macos(10.10)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //区域监测是否可用, 已经弃用的方法。使用+ isMonitoringAvailableForClass:代替。
    + (BOOL)regionMonitoringAvailable API_DEPRECATED_WITH_REPLACEMENT("+isMonitoringAvailableForClass:", ios(4.0, 7.0), macos(10.8, 10.10)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //是否启用了区域监测,  弃用。使用+isMonitoringAvailableForClass:和+authorizationStatus代替。
    + (BOOL)regionMonitoringEnabled API_DEPRECATED("Use +isMonitoringAvailableForClass: and +authorizationStatus instead", ios(4.0, 6.0), macos(10.8, 10.10)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //确定设备是否支持测距。
    //如果没有,所有发射信标的尝试都将失败。
    + (BOOL)isRangingAvailable API_AVAILABLE(ios(7.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //查看调用应用程序的当前授权状态。
    + (CLAuthorizationStatus)authorizationStatus API_AVAILABLE(ios(4.2), macos(10.7));
    
    //定位的代理对象
    @property(assign, nonatomic, nullable) id<CLLocationManagerDelegate> delegate;
    
    //启用定位服务, 弃用。使用+ locationServicesEnabled代替。
    @property(readonly, nonatomic) BOOL locationServicesEnabled API_DEPRECATED_WITH_REPLACEMENT("+locationServicesEnabled", ios(2.0, 4.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //允许应用程序指定在其应用程序中使用的位置将与标准位置权限对话框一起显示。
    //这个属性需要是在调用startUpdatingLocation之前设置。
    //弃用。在Info中设置目的字符串。plist使用关键NSLocationUsageDescription。
    @property(copy, nonatomic, nullable) NSString *purpose API_AVAILABLE(macos(10.7)) API_DEPRECATED("Set the purpose string in Info.plist using key NSLocationUsageDescription", ios(3.2, 6.0)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //指定用户活动的类型。当前影响的行为如
    //确定何时可以自动暂停位置更新。
    //默认情况下,使用CLActivityTypeOther。
    @property(assign, nonatomic) CLActivityType activityType API_AVAILABLE(ios(6.0), watchos(4.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED;
    
    //指定以米为单位的最小更新距离。客户将不会被通知移动较少高于所述值,
    //除非精确度有所提高。通过kCLDistanceFilterNone通知所有动作。
    //默认情况下,使用kCLDistanceFilterNone。
    @property(assign, nonatomic) CLLocationDistance distanceFilter;
    
    //所需的定位精度。定位服务将尽其所能你期望的准确性。
    //然而,这并不能保证。优化电源性能,请确保为您的使用场景指定适当的精度
    //(例如,当只需要一个粗糙的位置时,使用一个较大的精度值)。
    //使用kCLLocationAccuracyBest达到最佳的准确度。
    //使用kCLLocationAccuracyBestForNavigation进行导航。
    //默认值因平台而异。
    @property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;
    
    //指定位置更新可以在可能的情况下自动暂停。
    //默认情况下,对于与iOS 6.0或更高版本链接的应用程序,这是肯定的。
    @property(assign, nonatomic) BOOL pausesLocationUpdatesAutomatically API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //允许后台位置更新
    //默认情况下,这是不适用于iOS 9.0或更高版本的应用程序,
    //带有uibackgroundmode的设置,在Info中包含"location"。
    //plist,你必须设置否者程序旧崩溃
    //还可以在运行时调用时将此属性设置为YES, 提高性能
    //开启位置更新 -startUpdatingLocation 意图在后台继续定位。
    //当uibackgroundmode不包含时,将此属性设置为YES
    //将此属性重置为NO等同于省略“location”
    // UIBackgroundModes值。仍然允许访问位置当应用程序正在运行时(即没有暂停),
    //并且已经运行足够的授权(即它在使用授权时已经存在使用,或它总是有授权)。
    //然而,这款应用仍然是遵守通常的任务暂停规则。
    //参见-requestWhenInUseAuthorization and -requestAlwaysAuthorization for
    //关于可能的授权值的更多细节。
    @property(assign, nonatomic) BOOL allowsBackgroundLocationUpdates API_AVAILABLE(ios(9.0), watchos(4.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED;
    
    //显示后台定位的指示器
    //指定应用程序使用continuous时显示一个指示器后台位置更新。
    //起动连续背景位置更新要求app设置uibackgroundmode加入"location"
    //并将属性allowsBackgroundLocationUpdates设置为YES之前
    //调用-startUpdatingLocation,目的是继续在后台定位。
    //请注意,此属性仅适用于始终具有授权的应用程序。
    //对于授权使用的应用程序,在何时显示指示符使用持续的后台位置更新,
    //以维护用户可见性和应用程序仍然在使用。
    //此属性的默认值为NO。
    @property(assign, nonatomic) BOOL showsBackgroundLocationIndicator API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //定位位置
    //收到的最后一个位置。将为nil,直到接收到位置
    @property(readonly, nonatomic, copy, nullable) CLLocation *location;
    
    //标题, 弃用。使用+ headingAvailable代替。
    @property(readonly, nonatomic) BOOL headingAvailable API_DEPRECATED_WITH_REPLACEMENT("+headingAvailable", ios(3.0, 4.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //标题过滤器
    //指定标题服务更新所需的最小程度更改量。
    //客户不会更新的通知少于规定的过滤值。
    //通过kCLHeadingFilterNone通知所有更新。
    //默认情况下,使用1度。
    @property(assign, nonatomic) CLLocationDegrees headingFilter API_AVAILABLE(ios(3.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //指定要引用的标题计算的物理设备方向。默认情况下,
    //使用CLDeviceOrientationPortrait。
    //CLDeviceOrientationUnknown CLDeviceOrientationFaceUp,CLDeviceOrientationFaceDown被忽略。
    @property(assign, nonatomic) CLDeviceOrientation headingOrientation API_AVAILABLE(ios(4.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //返回收到的最新标题更新,如果没有可用的,返回nil。
    @property(readonly, nonatomic, copy, nullable) CLHeading *heading API_AVAILABLE(ios(4.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //框架能够支持的最大区域大小(以距离中心点的距离为单位)。
    //试图注册一个比这个更大的区域会导致kclerrorregional monitoringfailure。
    //此值可能根据设备的硬件特性以及动态变化的资源约束而变化。
    @property (readonly, nonatomic) CLLocationDistance maximumRegionMonitoringDistance API_AVAILABLE(ios(4.0), macos(10.8)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //检索当前被监视区域的一组对象。如果有位置管理器
    //已被指示监视某个区域,在此或之前启动应用程序期间,它将监视该区域
    //出现在本集合内。
    @property (readonly, nonatomic, copy) NSSet<__kindof CLRegion *> *monitoredRegions API_AVAILABLE(ios(4.0), macos(10.8)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //检索一组对象,这些对象表示此位置管理器积极为其提供范围。
    @property (readonly, nonatomic, copy) NSSet<__kindof CLRegion *> *rangedRegions API_AVAILABLE(ios(7.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //When +authorizationStatus == kCLAuthorizationStatusNotDetermined,
    //调用此方法将触发“在使用中”请求提示用户授权。
    //如果可能,执行响应调用引导用户请求基于位置的服务,使其原因因为提示会很清楚。
    //由于以下原因而导致的任何授权更改提示将通过通常的委托回调反映:
    // locationmanager:didChangeAuthorizationStatus:。
    //如果收到,“在使用中”授权授予对用户的访问权限位置通过-startUpdatingLocation/-startRangingBeaconsInRegion,
    //而在前景。如果更新已经开始时,去后台,然后一个状态栏横幅将显示维护用户可见性,更新将继续,直到停止
    //通常情况下,或应用程序被用户杀死。
    //“在使用中”授权不启用区域上的监测API,
    //重要的位置变化,或访问,和-startUpdatingLocation将从后台调用不会成功。
    //When +authorizationStatus
    //通常在第一次调用之后)这个方法不会做任何事情。
    //NSLocationWhenInUseUsageDescription键必须在你的Info.plist;
    //否则,这个方法什么都不做,就像你的应用程序一样假定在使用授权时不支持。
    - (void)requestWhenInUseAuthorization API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos);
    
    //When +authorizationStatus == kCLAuthorizationStatusNotDetermined,调用此方法将触发“总是”请求提示用户授权。
    //如果可能,执行响应调用引导用户请求基于位置的服务,使其知道原因,因为提示会很清楚。
    //由于以下原因而导致的任何授权更改提示将通过通常的委托回调反映:locationmanager:didChangeAuthorizationStatus:。
    //如果收到,“总是”授权授予对用户的访问权限通过任何CLLocationManager API定位,并授予访问权限可发射的监测API,例如地理会议/区域监测,重要的位置访问,等。
    //即使被用户杀死,启动受监测区域或访问模式触发的事件将导致a重新启动。
    //“始终”授权对用户隐私构成重大风险因此,除非后台启动行为,否则不鼓励请求确实是必需的。
    //不要调用+requestAlwaysAuthorization,除非你认为用户会感谢你这样做。
    //目前有“使用时”授权的应用程序以前从未要求“总是”授权可以使用此方法只请求“总是”授权一次。
    //否则,如果 +authorizationStatus通常在第一次调用之后)这个方法不会做任何事情。
    //两个nslocationalways sandwhenuseusagedescription和NSLocationWhenInUseUsageDescription键必须在你的Info.plist;
    //否则,这个方法什么都不做,就像你的应用程序一样假设不始终支持授权。
    - (void)requestAlwaysAuthorization API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED;
    
    //开始更新位置
    - (void)startUpdatingLocation API_AVAILABLE(watchos(3.0)) __TVOS_PROHIBITED;
    
    //停止更新位置
    - (void)stopUpdatingLocation;
    
    //请求单个位置更新。
    //本服务将根据准确的位置进行定位达到要求的精确度。
    //位置更新将被交付通过标准委托回调,即locationManager:didUpdateLocations:
    //如果可用的最佳位置精度较低,则为超时后通过标准委托回调传递。
    //如果无法确定位置,locationManager:didFailWithError:委托回调将以未知的错误位置交付。
    //只有一个未完成的位置请求,此方法可以不得与startUpdatingLocation或allowDeferredLocationUpdates。
    //调用这些方法中的任何一个都会立即取消位置请求。该方法可以使用stopUpdatingLocation显式取消请求。
    - (void)requestLocation API_AVAILABLE(ios(9.0)) API_UNAVAILABLE(macos);
    
    //开始更新标题
    - (void)startUpdatingHeading API_AVAILABLE(ios(3.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //停止更新标题
    - (void)stopUpdatingHeading API_AVAILABLE(ios(3.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //立即取消航向校准
    - (void)dismissHeadingCalibrationDisplay API_AVAILABLE(ios(3.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //开始监视重要的位置变化。此服务的行为不受所需精确度的影响或距离过滤器属性。
    //位置将通过与标准相同的委托回调传递位置服务。
    - (void)startMonitoringSignificantLocationChanges API_AVAILABLE(ios(4.0), macos(10.7)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //停止监视重要的位置变化
    - (void)stopMonitoringSignificantLocationChanges API_AVAILABLE(ios(4.0), macos(10.7)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //开始监视指定的区域。设计精度表示穿过该地区边界的距离该申请书希望获通知该区域边界已越过。
    //这有助于预防当使用者在该区域的边界时,会有重复的通知。
    //这一价值将得到最大限度的尊重,如果要求的精确度相对于区域的大小较大,或者设备的尺寸不高,则可能不受尊重能够提供所需的精度。
    //如果该应用程序已经监视了具有相同标识符的相同类型的区域,那么它将被监视从监视中删除。
    //这是异步进行的,可能不会立即反映在monitoredRegions。
    - (void)startMonitoringForRegion:(CLRegion *)region
                     desiredAccuracy:(CLLocationAccuracy)accuracy API_DEPRECATED_WITH_REPLACEMENT("-startMonitoringForRegion:", ios(4.0, 6.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //停止监控指定区域。调用stopMonitoringForRegion是有效的:对于已注册的区域用于在此或之前启动应用程序期间使用不同的location manager对象进行监视。
    //这是异步进行的,可能不会立即反映在monitoredRegions。
    - (void)stopMonitoringForRegion:(CLRegion *)region API_AVAILABLE(ios(4.0), macos(10.8)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //开始监视指定的区域。
    //若本应用程式已监察同一类型及同一标识符的区域,将从监视中删除。
    //对于循环区域,区域监测服务将优先考虑按面积划分的地区,倾向于较小的地区而不是较大的地区。
    //这是异步进行的,可能不会立即反映在monitoredRegions。
    - (void)startMonitoringForRegion:(CLRegion *)region API_AVAILABLE(ios(5.0), macos(10.8)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //异步检索指定区域的缓存状态。状态通过以下方式返回给委托 locationManager:didDetermineState:forRegion:。
    - (void)requestStateForRegion:(CLRegion *)region API_AVAILABLE(ios(7.0), macos(10.10)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //开始计算指定区域内信标的范围
    - (void)startRangingBeaconsInRegion:(CLBeaconRegion *)region API_AVAILABLE(ios(7.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //停止指定区域的计算范围
    - (void)stopRangingBeaconsInRegion:(CLBeaconRegion *)region API_AVAILABLE(ios(7.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //表示应用程序将允许位置管理器延迟执行位置更新,直到满足退出条件。
    //这可能使设备进入低功耗状态,稍后更新交货。
    //一旦满足退出条件,位置管理器就会继续正常更新,直到再次调用此方法。
    //退出条件、距离和超时,可以使用常量指定cllocationdistancemax和CLTimeIntervalMax,如果你是的话试图达到无限的距离或超时。
    //CLLocationManagerDelegate将继续接收正常的更新只要应用程序仍然在前台。
    //在这个过程中在后台,设备可能会进入低功耗状态指定距离和时间间隔的部分。而在这状态,地点将合并,以便稍后交付。
    //位置更新将被推迟尽可能多的合理保存力量。如果另一个进程正在使用位置,设备可能不会进入a低功耗状态,更新将正常进行。递延如果设备退出和重新进入低功率状态。
    //所有位置更新,包括延迟更新,将通过委托回调locationManager:didUpdateLocations:当延迟更新结束时,管理器将调用委托调locationManagerDidFinishDeferredUpdates:withError:。一个错误如果经理不延迟更新和退出,将返回没有达到标准。
    - (void)allowDeferredLocationUpdatesUntilTraveled:(CLLocationDistance)distance
                          timeout:(NSTimeInterval)timeout API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //如果先前已启用,则不允许延迟位置更新。任何优秀的将发送更新信息,并恢复定期的位置更新。
    - (void)disallowDeferredLocationUpdates API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(macos) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    
    //如果设备支持延迟位置更新,返回YES,否则返回NO
    + (BOOL)deferredLocationUpdatesAvailable API_AVAILABLE(ios(6.0), macos(10.9)) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
    

    添加视图设置代理

        //添加地图视图到控制器
        [self.view addSubview:self.mapView];
    
        /** 申请授权, AlwaysAuthorization:永久授权 */
        [self.locationManager requestAlwaysAuthorization];
        
        
        /** 开始更新位置信息, 调用这个方法后, 才有代理回调 */
        [self.locationManager startUpdatingLocation];
    

    地址解析方法

    /** 地址解析, 把地址字符串转成坐标值 */
    - (void)geocodingAddress{
        /** 把省会的名字做地址解析 */
        CLGeocoder * coder = [[CLGeocoder alloc] init];
        [coder geocodeAddressString:self.locationString completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
            CLPlacemark * placemark = placemarks.lastObject;
            CLLocationCoordinate2D coor = placemark.location.coordinate;
            
            /** 回到主线程刷新UI界面 */
            dispatch_async(dispatch_get_main_queue(), ^{
                
                /** 设置当前位置的图钉, MKPointAnnotation:采用MKAnnotation协议的对象, pinView:系统图钉 */
                MKPointAnnotation * point = [[MKPointAnnotation alloc] init];
                point.coordinate = coor;
                /** 添加🐱点, 这个方法会调用下面的 设置锚点视图 */
                [self.mapView addAnnotation:point];
                
                /** 将地图的显示区域变小 */
                MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coor, 1000, 1000);
                [self.mapView setRegion:region animated:YES];
            });
            
        }];
    }
    

    定位的代理回调

    #pragma mark - 定位代理
    /** 更新位置信息后的回调, 这个方法会重覆调用 */
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
        /** 获取到当前位置 */
        CLLocation * currLocation = locations.lastObject;
        /** 设置当前位置的图钉, MKPointAnnotation:采用MKAnnotation协议的对象, pinView:系统图钉 */
        MKPointAnnotation * point = [[MKPointAnnotation alloc] init];
        point.coordinate = currLocation.coordinate;
        /** 位置信息, 地址反向解析, 得到位置的名称 */
        CLGeocoder * coder = [[CLGeocoder alloc] init];
        [coder reverseGeocodeLocation:currLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
            CLPlacemark * placemark = placemarks.lastObject;
            point.title = [NSString stringWithFormat:@"当前:%@", placemark.name];
        }];
        /** 添加图钉, 这个方法会调用下面的 代理方法 */
        [self.mapView addAnnotation:point];
        /** 将地图的显示区域变小 */
        MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(currLocation.coordinate, 1000, 1000);
        [self.mapView setRegion:region animated:YES];
    }
    

    地图代理回调

    #pragma mark - 地图代理
    /** 设置锚点视图 */
    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
        MKPinAnnotationView * pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"pinView"];
        if (pinView == nil) {
            pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pinView"];
        }
        pinView.animatesDrop = YES;
        pinView.canShowCallout = YES;
        
        
        return pinView;
    }
    

    //注意:只要是想后台获取用户的位置,就必须开启后台模式
    项目->TARGETS->Capabilities-> Background Modes 勾线 Location updates

    屏幕快照 2018-09-15 16.05.46.png

    设置定位锚点

    1./指定地图显示中心和显示区域
      为了控制地图显示指定区域,只要两步即可。
      1、创建一个MKCoordinateRegion结构体变量,该结构体变量包含center,span两个成员,其中center控制显示区域的中心,span控制显示区域的范围。
      2、将MKMapView的region属性设为制定的MKCoordinateRegion结构体变量。
      iOS中为开发者提供了以下三种地图类型,开发者可以通过设置MKMapView的mapViewType设置地图类型。
      (1)MKMapTypeStandard 普通地图
      (2)MKMapTypeSatellite 卫星云图
      (3)MKMapTypeHybrid 普通地图覆盖于卫星云图之上
      2./在地图中使用大头针
      (1)通过MapView的addAnnotation方法可以添加一个大头针到地图上
      (2)通过MapView的addAnnotations方法可以添加多个大头针到地图上
        - (void)addAnnotation:(id <MKAnnotation>)annotation;
        说明:需要传入一个遵守了MKAnnotation协议的对象(下面代码中进行演示)

        /** 添加图钉, 这个方法会调用下面的 代理方法 */
        [self.mapView addAnnotation:point];
    

    当你调用了- (void)addAnnotation:(id <MKAnnotation>)annotation;后系统会自动调用下面的回调
    可以在下面的代理方法中实现自定义的图钉样式

    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
    {
        static NSString *ID = @"anno";
        MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];
        if (annoView == nil) {
            annoView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID];
            // 显示气泡
            annoView.canShowCallout = YES;
            // 设置绿色
            annoView.pinColor = MKPinAnnotationColorGreen;
        }
        
        return annoView;
    }
    

    相关文章

      网友评论

        本文标题:iOS-系统原生的地图和定位简单使用

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