iOS开发系列--地图与定位源代码详解

2020-01-18 17:38:32王振洲

 

用户位置跟踪

在很多带有地图的应用中默认打开地图都会显示用户当前位置,同时将当前位置标记出来放到屏幕中点方便用户对周围情况进行查看。如果在iOS6或者iOS7中实现这个功能只需要添加地图控件、设置用户跟踪模式、在-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation代理方法中设置地图中心区域及显示范围。但是在iOS8中用法稍有不同:

1.由于在地图中进行用户位置跟踪需要使用定位功能,而定位功能在iOS8中设计发生了变化,因此必须按照前面定位章节中提到的内容进行配置和请求。

2.iOS8中不需要进行中心点的指定,默认会将当前位置设置中心点并自动设置显示区域范围。

了解以上两点,要进行用户位置跟踪其实就相当简单了,值得一提的是-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation这个代理方法。这个方法只有在定位(利用前面章节中的定位内容)到当前位置之后就会调用,以后每当用户位置发生改变就会触发,调用频率相当频繁。

大头针

在iOS开发中经常会标记某个位置,需要使用地图标注,也就是大家俗称的“大头针”。只要一个NSObject类实现MKAnnotation协议就可以作为一个大头针,通常会重写协议中coordinate(标记位置)、title(标题)、subtitle(子标题)三个属性,然后在程序中创建大头针对象并调用addAnnotation:方法添加大头针即可(之所以iOS没有定义一个基类实现这个协议供开发者使用,多数原因应该是MKAnnotation是一个模型对象,对于多数应用模型会稍有不同,例如后面的内容中会给大头针模型对象添加其他属性)。

KCAnnotation.h


//
// KCAnnotation.h
// MapKit
//
// Created by Kenshin Cui on 14/3/27.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface KCAnnotation : NSObject<MKAnnotation>

@property (nonatomic) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

@end

KCMainViewController.m


//
// KCMainViewController.m
// MapKit Annotation
//
// Created by Kenshin Cui on 14/3/27.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
// 37.785834  -122.406417
// 39.92 116.39

#import "KCMainViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import "KCAnnotation.h"

@interface KCMainViewController ()<MKMapViewDelegate>{
  CLLocationManager *_locationManager;
  MKMapView *_mapView;
}

@end

@implementation KCMainViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  
  [self initGUI];
}

#pragma mark 添加地图控件
-(void)initGUI{
  CGRect rect=[UIScreen mainScreen].bounds;
  _mapView=[[MKMapView alloc]initWithFrame:rect];
  [self.view addSubview:_mapView];
  //设置代理
  _mapView.delegate=self;
  
  //请求定位服务
  _locationManager=[[CLLocationManager alloc]init];
  if(![CLLocationManager locationServicesEnabled]||[CLLocationManager authorizationStatus]!=kCLAuthorizationStatusAuthorizedWhenInUse){
    [_locationManager requestWhenInUseAuthorization];
  }
  
  //用户位置追踪(用户位置追踪用于标记用户当前位置,此时会调用定位服务)
  _mapView.userTrackingMode=MKUserTrackingModeFollow;
  
  //设置地图类型
  _mapView.mapType=MKMapTypeStandard;
  
  //添加大头针
  [self addAnnotation];
}

#pragma mark 添加大头针 
-(void)addAnnotation{
  CLLocationCoordinate2D location1=CLLocationCoordinate2DMake(39.95, 116.35);
  KCAnnotation *annotation1=[[KCAnnotation alloc]init];
  annotation1.title=@"CMJ Studio";
  annotation1.subtitle=@"Kenshin Cui's Studios";
  annotation1.coordinate=location1;
  [_mapView addAnnotation:annotation1];
  
  CLLocationCoordinate2D location2=CLLocationCoordinate2DMake(39.87, 116.35);
  KCAnnotation *annotation2=[[KCAnnotation alloc]init];
  annotation2.title=@"Kenshin&Kaoru";
  annotation2.subtitle=@"Kenshin Cui's Home";
  annotation2.coordinate=location2;
  [_mapView addAnnotation:annotation2];
}

#pragma mark - 地图控件代理方法
#pragma mark 更新用户位置,只要用户改变则调用此方法(包括第一次定位到用户位置)
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
  
  NSLog(@"%@",userLocation);
  //设置地图显示范围(如果不进行区域设置会自动显示区域范围并指定当前用户位置为地图中心点)
  //  MKCoordinateSpan span=MKCoordinateSpanMake(0.01, 0.01);
  //  MKCoordinateRegion region=MKCoordinateRegionMake(userLocation.location.coordinate, span);
  //  [_mapView setRegion:region animated:true];
}

@end