综述
地图相关类前缀CL: Core Location。
一.定位
CLLocationManager
The CLLocationManager object is your entry point to the location service.
用于定位
构造方法
- (CLLocationManager *)locationManager
{
if (!_locationManager) {
//判断定位功能是否打开
if ([CLLocationManager locationServicesEnabled]) {
_locationManager = [[CLLocationManager alloc]init];
_locationManager.delegate = self;
[_locationManager requestWhenInUseAuthorization];
//设置寻址精度
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.distanceFilter = 5.0;
[_locationManager startUpdatingLocation];
}
}
return _locationManager;
}
定位权限
- (void)getUserLocationAuthorization{
//判断当前设备定位服务是否打开
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"设备尚未打开定位服务");
}
//判断当前设备版本大于iOS8以后的话执行里面的方法
if ([UIDevice currentDevice].systemVersion.floatValue >=8.0) {
//当用户使用的时候授权
[self.locationManager requestWhenInUseAuthorization];
}
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
NSString *message = @"您的手机目前未开启定位服务,如欲开启定位服务,请至设定开启定位服务功能";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"无法定位" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
[alertView show];
}
}
设置显示范围
遵循CLLocationManagerDelegate
协议,实现代理方法
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
[self.locationManager stopUpdatingHeading];
//地址
self.userLocation = [locations lastObject];
//显示范围
double latitudeSpan = fabs(self.latitude - self.userLocation.coordinate.latitude) * 3;
double longitudeSpan = fabs(self.longitude - self.userLocation.coordinate.longitude) *3;
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeSpan, longitudeSpan);
MKCoordinateRegion regoin = MKCoordinateRegionMake(self.userLocation.coordinate, span);
[self.mapView setRegion:regoin animated:YES];
}
二.地图
初始化
- (MKMapView *)mapView
{
if (!_mapView) {
_mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0,0, kScreenWidth, kScreenHeight)];
//设置用户的跟踪模式
_mapView.userTrackingMode = MKUserTrackingModeFollow;
//设置标准地图
_mapView.mapType = MKMapTypeStandard;
// 不显示罗盘和比例尺
if (@available(iOS 9.0, *)) {
_mapView.showsCompass = NO;
_mapView.showsScale = NO;
}
// 开启定位
_mapView.showsUserLocation = YES;
_mapView.delegate = self;
//初始位置及显示范围
MKCoordinateSpan span=MKCoordinateSpanMake(0.021251, 0.016093);
[_mapView setRegion:MKCoordinateRegionMake(self.mapView.userLocation.coordinate, span) animated:YES];
}
return _mapView;
}
设置覆盖物
- (void)initCarPoint{
//创建CLLocation 设置经纬度
CLLocation *loc = [[CLLocation alloc]initWithLatitude:self.latitude longitude:self.longitude];
CLLocationCoordinate2D coord = [loc coordinate];
//创建标题
NSString *titile = @"救护车";
MSCarPoint *myPoint = [[MSCarPoint alloc] initWithCoordinate:coord andTitle:titile];
//添加标注
[self.mapView addAnnotation:myPoint];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation{
static NSString *placemarkIdentifier = @"PointAnnotation";
if ([annotation isKindOfClass:[MSCarPoint class]]){
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:placemarkIdentifier];
if([annotation.title isEqualToString:@"救护车"]){
//救护车
annotationView.image = [UIImage imageNamed:@"icon"];
}
return annotationView;
}
return nil;
}
重定位我的位置
- (void)resetLocation:(id)sender {
// 定位到我的位置
[self.mapView setCenterCoordinate:_mapView.userLocation.coordinate animated:YES];
}
三.地理编码
CLGeocoder
CLGeocoder: 地理编码。
地理编码:根据给定的地名,获得具体的位置信息(比如经纬度、地址的全称等)
反地理编码:根据给定的经纬度,获得具体的位置信息
CLPlacemark
CLPlacemark: 详细的地址位置信息,包括如下主要属性。
地理位置 @property (nonatomic, readonly) CLLocation *location;
区域 @property (nonatomic, readonly) CLRegion *region;
详细的地址信息 @property (nonatomic, readonly) NSDictionary *addressDictionary;
地址名称 @property (nonatomic, readonly) NSString *name;
城市 @property (nonatomic, readonly) NSString *locality;
CLLocation
CLLocation:地理位置
根据地名进行标注代码实例
//初始化地理编码器
let coder = CLGeocoder()
//根据地名字符串返回CLPlacemark数组和error
coder.geocodeAddressString(area.name) { (placeMark, error) in
//使用guard进行前置条件判断,为空时打印错误然后终止方法
guard placeMark != nil else {
print(error ?? "未知错误")
return
}
//获取地理位置详细信息数组中第一个
let place = placeMark?.first
//初始化标注
let annotation = MKPointAnnotation()
//指定标注标题及副标题
annotation.title = self.area.name
annotation.subtitle = self.area.province
//获取CLPlacemark中的CLLocation
if let location = place?.location{
//设置标注经纬度
annotation.coordinate = location.coordinate
//显示标注
self.mapView.showAnnotations([annotation], animated: true)
//选中标注
self.mapView.selectAnnotation(annotation, animated: true)
}
}
自定义图钉视图
遵循MKMapViewDelegate
协议,实现如下代理方法。
- (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id
代码如下。
// MARK: - map delegate
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
//判断是否是用户位置
if annotation is MKUserLocation {
//如果是用户当前位置,终止方法
return nil
}
//指定标注重用标识符
let mapId = "myAnnotationId"
//根据重用标识符获取标注视图(与cell重用原理类似)。 注:取出标注视图转为MKPinAnnotationView,自带图钉(只自定义左附加视图图片)
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: mapId) as? MKPinAnnotationView
//判断标注视图是否存在
if annotationView == nil {
//如果标注视图不存在,根据标注和标注重用标识符创建标注视图
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: mapId)
annotationView?.canShowCallout = true
}
//设置自定义icon视图
let iconView = UIImageView(frame: CGRect(x: 0, y: 0, width: 53, height: 53))
iconView.image = UIImage(named: "dislike")
//设置左附加视图图片
annotationView?.leftCalloutAccessoryView = iconView
//自定义图钉颜色 IOS9+
annotationView?.pinTintColor = UIColor.blue
//返回标注视图
return annotationView
}