直接正题,没得BB
首先说明一下室内定位从架构上严格来讲分为3步:
1、室内地图以及室内地图能相关的一些成熟API
2、以任意方式来获取室内定位的坐标
3、将室内定位的坐标转化成室内地图的API或者一种能兼容两者的转换方式
(可选)4、定位稳定性的滤波处理,试定位坐标点不出现 跳点、卡顿、掉帧、北偏角指向性错误等影响用户体验的处理方案
目前市场中室内定位资源比较散乱,主要分为地图供应商和定位服务商两种,也有将室内定位资源合并的企业,比如 某石科技
所以要是想对室内定位有研究的最好还是需要多方了解提供商的SDK相关信息
最近我们公司的室内定位项目马上杀青了,才有空写个博客散散心,总结一下iOS开发中踩过的坑:
1、手机端地图出现黑色无色模型,Web端出现透明模型。
2、路径导航无法规划路线。
3、无法绘制路径/SDK的相关方法/对象不执行。
4、地图对象创建后未销毁,造成第二次地图对象在规划路径的时候闪退、崩溃。
5、地图图标出现黑块。
6、返回上一级界面后未执行dealloc方法。
7、路径绕远。
8、U型弯道或L型弯道在路网吸附的模式下路过会出现跳点。
9、地图加载失败。
10、地图的绘制/解析慢。
========================分割线=========================
我的解决方案:
1、手机端地图出现黑色无色模型,Web端出现透明模型。
原因:这个是因为主题不兼容造成的,地图在SDK解析过程中根据资源包已经赋予其颜色属性了,如果没有相关资源包就默认为黑色
我使用的是蜂鸟视图,我们地图属性和显示是经过定制的,所以使用常规的主题就会造成黑块模型的出现。
WEB端JS的SDK做过相关处理,所以展示只是透明的模型。
解决:与其相关开发人员沟通,重新更新一个定制的主题即可。
2、路径导航无法规划路线。
原因:因为没有相关路网能抵达终点,路网的结构大致是这样的:
黑色区域是可到达的路网,红色是禁止掉的路网。明白了吧,如果终点的附近没有黑色路网,那么就代表这个点位是无法到达的
具体附近是多少,请注意供应商的API文档说明
解决:要和相关地图供应商联合解决这个问题,因为具体有那些点位可达/不可达,最好去实地勘探一下。
3、无法绘制路径/SDK的相关方法/对象不执行。
原因:请核对和官方的工程配置的做法是否有出入的地方,我出现这个原因是因为Other Linker Flags 中有个-ObjC错写成-Objc了,
C必须是大写,要么XCode编译器不会全编译框架中的OC文件,编译确实无错,但是一旦调用相关API的时候,这个API会引起崩溃等风险。
解决:Other Linker Flags 中添加-ObjC,大小写要分清
4、地图对象创建后未销毁,造成第二次地图对象在规划路径的时候闪退、崩溃。
原因:上一个地图对象成为了僵尸对象,在执行规划路线/或者其他操作的时候同时操作了僵尸对象,这个在崩溃的时候会有日志:
“你操作了一个不可操作的对象/指针”
解决:不管怎么使用地图视图对象,一定要在这个VC地图界面推出栈的时候(我用的push方法)查看是否执行dealloc方法,
如果没有,最好在点击退出的一瞬间将全部View remove掉,包括地图视图和相关View对象,然后指针置空,一定保证执行了dealloc。
保证程序稳定的情况下才能做更多事。
5、地图图标出现黑块。
原因:这个说起来很尴尬=。= 因为需求中有一个模拟导航,需要模拟这个定位点一点点移动在线路上,并且行走等事件。
是吧、、肯定用到了NSTimer啊。。。所以这个原因是因为在另一种我没想到的逻辑下退出界面,导致Timer没被销毁和暂停。
然后呢,地图又是OpenGL绘制的。。在下一次进入地图界面的时候,Timer占用了一个子线程,导致OpenGL一直没时间去绘制图标
导致地图一些元素显示成了黑块。。
解决:一定要统计有几种退出界面的方法,然后封装一个安全的方法(就是在不释放空对象的前提下能kill掉Timer),
在每种情况下退出界面都要执行这个能安全的kill掉Timer的方法,最后一定要监督dealloc方法的执行与否。
6、返回上一级界面后未执行dealloc方法。
原因:之前也提过很多了,主要是SDK中一些对象与主控制器的强引用造成的,这种很常见,要养成随时查看dealloc的习惯。
有些人会想了:现在不都ARC了么?谁还会关心这些啊?
这样想很不对,ARC可以为开发者节省很多代码,使用ARC以后再也不需要关心什么时候retain,什么时候release,
但是这并不意味你可以不思考内存管理,你可能需要经常性地问自己这个问题:谁持有这个对象?
解决:注意哪些是Strong引用的对象再被操作,什么时候把他置nil,保证能降低一个内存开销,性能上也是有很大的提升。
7、路径绕远。
原因:因为路网稀疏,导致想到达一个终点必须按照路网的规划来走,有兴趣的可以研究一下dijstra算法,
这个是大部分主流地图/导航的一个解决方案。
路网稀疏,只能这么走:
路网原因绕的远,不怪你不怪SDK,只怪地图路网没设计好。
解决:当然是与供应商沟通咯=。=。。程序又做不了什么。。。。
8、U型弯道或L型弯道在路网吸附的模式下路过会出现跳点。
原因:因为路径吸附的原理是判断你的定位点在路径周边大概多少米之内,将点位强制吸附到路径上
遇到U型弯道/L型弯道就会出现两个判定,,说白了就是两条路吸附范围发生重叠造成的判定混乱。。懂了吧 =。=
解决:还是沟通咯。。只能让他们把路网规划的更密一些,减少U型弯道的产生,至于L型么。。。小跳而已
谁也不会全程盯着手机看吧。。室内导航。。抬抬头就能知道该咋走了,,我就跳跳 =。=
9、地图加载失败。以及 10、地图的绘制/解析慢。
原因:因为整个地图文件是经过混淆的,而且解析引擎是C++(蜂鸟视图),解析完后再OpenGL绘制。。
听着都繁琐=。=。。当然慢了。。而且整个SDK流程是必须先经过认证后才能获得解析权限。。当然慢咯。。
解决:没办法。。但是可以把解析和UI操作分开来做:
我们希望多个任务同时(在多个线程里)执行,再他们都完成之后,再执行其他的任务,
于是可以建立一个分组,让多个任务形成一个组,下面的代码在组中多个任务都执行完毕之后再执行后续的任务:
先解析地图,然后页面随便展示一个 HUB或者Toast或者小菊花等等。。表示我们正在疯狂的画地图。。。
然后设置两个回调,一个地图成功和失败:
这个BOOL是在地图解析完后,准备执行下一个操作的时候的限制判断
如果解析成功则执行UI的创建和添加等等。。。如果失败则显示一个加载失败的图片。
注意,最后我是将所有操作全部回调到了主线程来执行的。。
这样就可以不卡死主线程的情况下先推出界面,同时进行解析、解析完成后再将地图添加到视图,失败了就展示失败的页面就好。
如果把解析(就是地图的构造方法)放在ViewDidLoad中,会卡死主线程1~8秒不等。。。这样肯定行不通的,比较平滑的处理先暂时只能这样。。
养成注释的习惯最好=。= 维护和二次开发的时候会很方便 =。=
晒一张我的一个主继承对象的h文件=。=
被人吐槽成把项目当SDK做。。
最后=。= Axc大法好。。。。