近些天用到了有关定位的功能,所以顺便把自己用到的一些相关知识整理如下.
一.定位要使用" CoreLocation "框架
想要定位,大概需要使用以下5个步骤:
1.首先创建一个"强引用"的位置管理器CLLocationManager
2.设置位置管理器的代理
3.请求用户授权(iOS8后方法)
>设置方法requestWhenInUseAuthorization 或requestAlwaysAuthorization
>配置plist文件 NSLocationWhenInUseUsageDescription 或 NSLocationAlwaysUsageDescription
>注意1对1对应
4.开启定位
startUpdatingLocation 对应的有停止定位stopUpdatingLocation
5.实现didUpdateLocations代理方法
>代理方法一直调用,会非常耗电。除非特殊需求(如导航),可以使用stopUpdatingLocation停止定位,实现一次定位
>除了停止定位,还可以设置管理器的distanceFilter,当用户改变位置一定值后才会调用。(如后面跟50,即改变50米后调用一次代理方法)-->持续定位
>desiredAccuracy-->定位精度-->将周围一定值的范围看作一个地点
比较两点之间的距离使用CLLocation的distanceFromLocation方法-- 注意计算出来的是直线距离
iOS9新特性-->后台定位-->allowsBackgroundLocationUpdates
>当用户授权为使用期间时,可以设置这个属性为YES,在plist中添加"Required background modes" 在字典中添加值"App registers for location updates".
二.地理编码和反地理编码都使用CLGeocoder类来实现.
地理编码使用 geocodeAddressString: completionHandler: 方法.将一个地名字符串转换为经纬度。
在此方法中得到一个装着CLPlacemark的数组。一个CLPlacemark表示一个地理坐标,有位置信息(经纬度),以及地理位置的详情,如下:
name 地名
thoroughfare 街道
subThoroughfare 街道相关信息,例如门牌等
locality 城市
subLocality 城市相关信息,例如标志性建筑
administrativeArea 直辖市
subAdministrativeArea 其他行政区域信息(自治区等)
postalCode 邮编
ISOcountryCode 国家编码
country 国家
inlandWater 水源,湖泊
ocean 海洋
areasOfInterest 关联的或利益相关的地标
将CLPlacemark中的经纬度取出,就完成了地理编码
反地理编码使用reverseGeocodeLocation: completionHandler: 方法.将一个包含经纬度的CLLocation传进去,得到位置信息,就是反地理编码。
在得到的CLPlacemark中取出name信息即可。
三.mapView的基本使用需要用到 "MapKit 框架
注意:在storyBoard中使用到非UIKit的框架,要在项目的TARGETS-->General-->Linked Frameworks and Libraries中点击+号添加框架
1.定位到用户位置
1.1 创建位置管理器并请求用户授权
1.2 设置mapView的跟踪模式userTrackingMode
MKUserTrackingModeNone //不跟踪
MKUserTrackingModeFollow //跟踪位置
MKUserTrackingModeFollowWithHeading //跟踪位置和移动方向
2.设置用户位置大头针的属性
2.1 设置mapView的代理,实现协议,在didUpdateUserLocation方法中拿到MKUserLocation类型的大头针
2.2 userLocation有location、title、subtitle属性,根据location反地理编码拿到CLPlacemark并赋值给title和subtitle即可
3.回到用户当前位置
3.1 确定当前位置(region-->MKCoordinateRegion)
确定一个区域和确定一个圆类似,需要且只需要确定两个元素:1.中心点经纬度CLLocationCoordinate2D-->self.mapView.userLocation.coordinate 2.经纬度跨度span-->MKCoordinateSpan 两个都是结构体,直接make。
3.2 如何确定系统默认经纬度跨度 --> 在mapView的代理方法regionDidChangeAnimated中,当地图区域改变时回自动调用,在此方法中打印经纬度跨度。
如果需要动画回到当前位置,调用mapView的 setRegion: animated:
4.放大(缩小)地图
放大和缩小地图其实就是:"当前"地图显示的中心点经纬度不变,经纬度跨度(span)缩小或增大2倍;
注意:在回到当前位置设置region时的中心点经纬度是定位到用户的经纬度(userLocation),而放大缩小地图的中心点经纬度是当前地图界面的中心点经纬度。
四.添加大头针模型设计
1.导入框架
-->在模型类中导入mapKit框架
2.遵守协议
-->遵守MKAnnotation协议
3.实现属性
-->实现title\subtitle\coordinate(可直接跳进头文件复制,注意删除readonly修饰)
添加大头针 -->mapView的addAnnotation: 方法
#pragma mark 修改大头针颜色,动画掉落
mapView的viewForAnnotation代理方法中实现,这块和cell的创建基本一样
1.首先创建一个唯一的标识符ID
static NSString *ID = @"annotation"
2.根据ID去缓存池取:
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:ID];
3.如果取不到(为空),再创建
annotationView = [[MKAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:ID];
MKAnnotationView默认是没有界面的,MKPinAnnotationView继承自MKAnnotationView,可以设置大头针颜色,动画掉落效果。而父类MKAnnotationView中的属性方法其子类都有,如:
canShowCallout --> 能否显示大头针详情
leftCalloutAccessoryView \ rightCalloutAccessoryView \ detailCalloutAccessoryView-->分别对应左\右\详情的视图.
注意如果大头针没有设置title属性,就不能显示左右和详情视图。如果同时设置了大头针的subtitle和detailCalloutAccessoryView,会显示detailCalloutAccessoryView。
在代理方法中如果直接return nil 系统会默认创建一个系统样式的大头针--> 当需要系统蓝光圈的大头针时,可以判断代理方法中参数的类型,匹配就return nil
#pragma mark 自定义实现动画掉落效果
自定义动画效果在mapView的代理方法didAddAnnotationViews 中实现,此方法在加载完大头针的view时系统自动调用
自定义动画掉落思路: 1.保存大头针位置 2.修改大头针位置的Y值 3.动画返回到大头针默认位置
注意:如果要取消系统默认蓝光圈(MKModernUserLocationView类型)的动画掉落效果,在didAddAnnotationViews 代理方法中判断传进来的MKAnnotationView类型(MKModernUserLocationView是私有方法,用NSClassFromString方法替代 [MKModernUserLocationView class])
#pragma mark 封装代码
这里的封装代码和tableViewCell类似,不再赘述.
只是要注意如果不给大头针添加模型,系统会自动调用set方法,所以在工作中处理数据的代码可以放在set方法中。注意调用父类方法[super setAnnotation:annotation];
五.实现导航
地图导航所需的数据拿不到,交由苹果处理,在中国苹果交友高德地图处理。由于封装的比较好,我们本质上只需要一行代码:
MKMapItem openMapsWithItems: launchOptions:
根据所需传入的参数倒推即可。
所需正序步骤:
1.地理编码目的地位置
>>使用CLGeocoder进行地理编码,得到CLPlacemark
2.转换CLPlacemark --> MKPlacemark
MKPlacemark *mkPlacemark = [[MKPlacemark alloc] initWithPlacemark:placemark];
3.获取当前位置和目的地mapItem
//目的地的item
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:mkPlacemark];
//当前位置的item
MKMapItem *currentmapItem = [MKMapItem mapItemForCurrentLocation];
4.开始导航
MKMapItem openMapsWithItems: launchOptions:
第一个参数传入目的地和当前位置的数组,第二个是选项的字典。如下:
//keys
MKLaunchOptionsMapCenterKey:地图中心的坐标(NSValue)
MKLaunchOptionsMapSpanKey:地图显示的范围(NSValue)
MKLaunchOptionsShowsTrafficKey:是否显示交通信息(boolean NSNumber)
//MKLaunchOptionsDirectionsModeKey: 导航类型(NSString)
{
MKLaunchOptionsDirectionsModeDriving:驾车
MKLaunchOptionsDirectionsModeWalking:步行
}
//MKLaunchOptionsMapTypeKey:地图类型(NSNumber)
enum {
MKMapTypeStandard = 0,
MKMapTypeSatellite,
MKMapTypeHybrid
};//MKLaunchOptionsCameraKey 3D地图效果
网友评论