ITdaan
首页
最新
原创
最火
关于
搜索答案
搜索本文相关内容
iOS百度地图SDK之实时绘制轨迹(后台仍执行)
本文转载自
shuidonglch
查看原文
2015/08/17
2896
地图
/
百度
/
后台
/
ios
/
百度地图
收藏
0
0
首先,对于百度地图SDK的配置和环境搭建就不做说明,需要的人可以博客中另一篇文章看 《iOS百度地图SDK基本使用》 ,本文的重点在于实现实时绘制轨迹的功能,并且对细节进行处理和优化
1、在AppDelegate.m文件中
[objc]
view plain
copy
#import "AppDelegate.h"
// BMapKit.h代表导入了所有的头文件
#import <BaiduMapAPI/BMapKit.h>
@interface
AppDelegate ()<BMKGeneralDelegate>
{
BMKMapManager
*mapManager;
}
@end
[objc]
view plain
copy
- (
BOOL
)application:(
UIApplication
*)application
didFinishLaunchingWithOptions
:(
NSDictionary
*)launchOptions {
// 要使用地图,首先需要初始化和启动BMKMapManager
mapManager = [[BMKMapManager
alloc
]init];
// 填入验证码, 如需要使用网络和授权验证服务,则需要设置代理信息
BOOL
ret = [mapManager
start
:
@"在这里填入的是密钥中的安全码"
generalDelegate
:nil
];
if
(!ret) {
NSLog(
@"地图管理器初始化失败"
);
}
else
{
NSLog(
@"初始化成功"
);
}
return
YES
;
}
2、在ViewController.m文件中
[objc]
view plain
copy
#import "ViewController.h"
#import <BaiduMapAPI/BMapKit.h>
#define normalLocationTag 1
#define compassLocationTag 2
@interface
ViewController () <BMKLocationServiceDelegate , BMKMapViewDelegate>
{
BMKMapView
*mapView;
BMKLocationService
*locationService;
// 用于手动验证
CLLocationManager
*locationManager;
// 用于记录经过的点
NSMutableArray
*locationPoint;
// 在地图上绘制的折线
BMKPolyline
*routeLine;
// 中间变量->location类型(地理位置)
CLLocation
*currentLocation;
}
@end
在viewDidLoad中将两个初始化体现出来
[objc]
view plain
copy
- (
void
)viewDidLoad {
[
super
viewDidLoad
];
// 1、所有的初始化操作
[
self
initObjects
];
// 2、所有的地图初始操作
[
self
operationForMap
];
}
初始化操作的封装后的方法
[objc]
view plain
copy
- (
void
)initObjects
{
// 初始化mapView
mapView = [[BMKMapView
alloc
]initWithFrame:CGRectMake(
0
,
1
2
0
,
self
.view
.bounds
.size
.width
,
self
.view
.bounds
.size
.height
)];
// 初始化locationService
locationService = [[BMKLocationService
alloc
]init];
}
对地图的各个参数进行操作封装后的方法
[objc]
view plain
copy
- (
void
)operationForMap
{
// 设置过滤距离,更新的最小间隔距离
[BMKLocationService
setLocationDistanceFilter
:
6
.0f
];
// 设置定位精度模式
/* tips:
以前使用了kCLLocationAccuracyBest--> 表示在使用电池的最高精度
现在使用了kCLLocationAccuracyBestForNavigation--> 表示在外接电源的时候的最高精度(有些在AppStore上架的APP由于过度依赖于高精度的定位,所以采用了这种耗电的定位设置)
*/
[BMKLocationService
setLocationDesiredAccuracy
:kCLLocationAccuracyBestForNavigation];
// 设置地图类型
mapView
.mapType
= BMKMapTypeSatellite;
// 设置是否需要热力图显示
[mapView
setBaiduHeatMapEnabled
:
NO
];
// 设置是否允许旋转地图
mapView
.rotateEnabled
=
YES
;<span style=
"white-space:pre"
> </span>
// .....对于地图还有很多设置,这里不一一列举,需要的话可以在文档中查到<span style="white-space:pre"> </span>
[
self
.view
addSubview
:mapView];
}
[objc]
view plain
copy
- (
void
)operationForLocation:(
BMKUserLocation
*)userLocation
{
// 1、检查移动的距离,移除不合理的点
if
(locationPoint
.count
>
0
) {
CLLocationDistance distance = [userLocation
.location
distanceFromLocation
:currentLocation];
if
(distance <
5
)
return
;
}
// 2、初始化坐标点数组
if
(
nil
== locationPoint) {
locationPoint = [[NSMutableArray
alloc
]
init
];
}
// 3、将合理的点添加到数组
[locationPoint
addObject
:userLocation
.location
];
// 4、作为前一个坐标位置辅助操作
currentLocation = userLocation
.location
;
// 5、开始画线
[
self
configureRoutes
];
// 6、实时更新用户位子
[mapView
updateLocationData
:userLocation];
}
[objc]
view plain
copy
#pragma mark - 点击两个button触发的事件
- (IBAction)startLocation:(
UIButton
*)button
{
// 由于IOS8中定位的授权机制改变 需要进行手动授权(导致程序无法进行定位的主要原因)
if
([[UIDevice
currentDevice
]
.systemVersion
floatValue
] >=
8
) {
locationManager = [[CLLocationManager
alloc
]
init
];
[locationManager
requestAlwaysAuthorization
];
[locationManager
requestWhenInUseAuthorization
];
}
// 开启用户定位
[locationService
startUserLocationService
];
// 开始先关闭地位图层(也就是定位的小圆点)-->用户体验问题
mapView
.showsUserLocation
=
NO
;
// 根据所点击的button来开启不同的定位模式
if
(button
.tag
== normalLocationTag) {
mapView
.userTrackingMode
= BMKUserTrackingModeFollow;
}
else
if
(button
.tag
== compassLocationTag) {
mapView
.userTrackingMode
= BMKUserTrackingModeFollowWithHeading;
}
mapView
.showsUserLocation
=
YES
;
// 1、通过比例调试地图的显示
#if 1
[mapView
setZoomEnabled
:
YES
];
mapView
.zoomLevel
=
1
9
;
// 级别是 3-19
#endif
#if 0
// 2、通过范围调试地图的显示
BMKCoordinateRegion adjustRegion = [mapView
regionThatFits
:BMKCoordinateRegionMake(locationService
.userLocation
.location
.coordinate
, BMKCoordinateSpanMake(
0
.03f
,
0
.03f
))];
[mapView
setRegion
:adjustRegion
animated
:
YES
];
#endif
}
[objc]
view plain
copy
#pragma mark - 视图的出现和消失(在其中设置代理和取消代理,优化内存管理)
- (
void
)viewWillAppear:(
BOOL
)animated
{
[mapView
viewWillAppear
];
mapView
.delegate
=
self
;
locationService
.delegate
=
self
;
}
- (
void
)viewWillDisappear:(
BOOL
)animated
{
[mapView
viewWillDisappear
];
// 一般情况下都需要在这里关闭掉代理,但是由于本程序需要在后台继续绘制轨迹,因为对应的代理方法是绘制轨迹,所以继续设置代理
mapView
.delegate
=
self
;
locationService
.delegate
=
self
;
}
[objc]
view plain
copy
#pragma mark - mapView的协议
- (
BMKOverlayView
*)mapView:(
BMKMapView
*)mapView
viewForOverlay
:(
id
<BMKOverlay>)overlay
{
if
([overlay
isKindOfClass
:[BMKPolyline
class
]]) {
BMKPolylineView
*polylineView = [[BMKPolylineView
alloc
]initWithPolyline:overlay];
// 设置划出的轨迹的基本属性-->也是使得定位看起来更加准确的主要原因
polylineView
.strokeColor
= [[UIColor
blueColor
]colorWithAlphaComponent:
0
.5
];
polylineView
.fillColor
= [[UIColor
blueColor
]colorWithAlphaComponent:
0
.8
];
polylineView
.lineWidth
=
6
.0
;
return
polylineView;
}
return
nil
;
}
[objc]
view plain
copy
#pragma mark - 绘制轨迹
-(
void
)configureRoutes
{
// 1、分配内存空间给存储经过点的数组
BMKMapPoint* pointArray = (
BMKMapPoint
*)malloc(
sizeof
(CLLocationCoordinate
2
D) * locationPoint
.count
);
// 2、创建坐标点并添加到数组中
for
(
int
idx =
0
; idx < locationPoint
.count
; idx++)
{
CLLocation
*location = [locationPoint
objectAtIndex
:idx];
CLLocationDegrees latitude = location
.coordinate
.latitude
;
CLLocationDegrees longitude = location
.coordinate
.longitude
;
CLLocationCoordinate
2
D coordinate = CLLocationCoordinate
2
DMake(latitude, longitude);
BMKMapPoint point = BMKMapPointForCoordinate(coordinate);
pointArray[idx] = point;
}
// 3、防止重复绘制
if
(routeLine) {
//在地图上移除已有的坐标点
[mapView
removeOverlay
:routeLine];
}
// 4、画线
routeLine = [BMKPolyline
polylineWithPoints
:pointArray
count
:locationPoint
.count
];
// 5、将折线(覆盖)添加到地图
if
(
nil
!= routeLine) {
[mapView
addOverlay
:routeLine];
}
// 6、清楚分配的内存
free(pointArray);
}
[objc]
view plain
copy
#pragma mark - 更新用户位置时所调用的三种方法
// 更新位置
- (
void
)didUpdateBMKUserLocation:(
BMKUserLocation
*)userLocation
{
// 说明:由于开启了“无限后台”的外挂模式(^-^)所以可以直接写操作代码,然后系统默认在任何情况执行,但是为了已读,规划代码如下
// 1、活跃状态
if
([UIApplication
sharedApplication
]
.applicationState
== UIApplicationStateActive) {
[
self
operationForLocation
:userLocation];
}
else
if
([UIApplication
sharedApplication
]
.applicationState
== UIApplicationStateBackground)
// 2、后台模式
{
[
self
operationForLocation
:userLocation];
}
// 3、不活跃模式
else
if
([UIApplication
sharedApplication
]
.applicationState
== UIApplicationStateInactive)
{
[
self
operationForLocation
:userLocation];
}
}
// 更新方向
- (
void
)didUpdateUserHeading:(
BMKUserLocation
*)userLocation
{
[mapView
updateLocationData
:userLocation];
}
// 定位失败了会调用
- (
void
)didFailToLocateUserWithError:(
NSError
*)error
{
NSLog(
@"did failed locate,error is %@"
,[error
localizedDescription
]);
}
到这里,代码就结束了,在viewWillDisappear中,依然没有关掉代理,是想让程序在锁屏后,或者是点击home键返回到桌面后仍然执行轨迹的绘制,但是仅仅设置代理是不够的,在没有进行配置的情况下,iOS系统最多可以让一个APP在有5秒钟的时间,用来进行保存和清理资源等任务。如果应用调用了UIApplication的beginBackgroundTaskWithExpirationHandler的方法,可以让APP在后台有10分组的运行时间,用来清理本地的缓存或者是进行数据的处理。超过了时间,APP便会被强制挂起
但是,就拿本例中所涉及的实时绘制轨迹来说,比如要开发一款跑步时绘制自己轨迹的应用,总不能跑步的时候都要将手机屏幕开着,并且还不能切换到其他地方,这样无疑增加了大量的电量消耗,所以,苹果也是为以下的几种提供了所谓的“无限后台”的外挂模式
1、Audio(音频播放)
2、Location/GPS(定位的实时更新)
3、Newsstand(杂志下载)
4、VoIP(网络电话)
所以,对于本例来说,苹果是允许启动外挂模式的,下面说明应该怎么配置这种模式
在info.plist文件中添加这样一项,Required background modes,然后这一项默认是数组类型,需要再在这项中添加一个item,默认生成了一项key为item0,接着将这个item0的value变为App registers for location updates
下面给出图例示范:
但是有人会想,那这样的话每个程序都可以开外挂了咯?话虽如此,但是在AppStore审核的时候,如果在plist文件中配置了这样的属性,那么AppStore会检测应用程序是否属于这种类型,如果不是的话,那么这样的APP就会被拒绝。
智能推荐
×
注意!
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。
猜您在找
android-百度地图:鹰眼轨迹的实时绘制
百度地图--实时显示轨迹
百度地图之实时定位与画轨迹以及纠偏问题总结
百度地图绘制轨迹点
百度地图轨迹绘制
【No317】最新web全栈架构师-56阶段对标百度T6-T7视频课程下载
【No45】Java菜鸟到大牛学习路线之实战篇
【No244】Spark 实时流处理视频教程
智能推荐
© 2014-2019 ITdaan.com
粤ICP备14056181号
×
收藏本文
添加到收藏夹 *
赞助商广告