基本思路
- 地图DidAppear后获取到MKMapKit自身蓝色小圆点的Frame值
- 地图DidAppear后获取到由LocationManage产生的Annotation对应的AnnotationView的Frame值
- 对比AnnotationView和BlueDot的Frame或者反推的Location来确定是否重叠
- 不重叠进行自动纠偏
如何获取BlueDot
通过Annotation获得
通过 mapView:viewForAnnotation: 获得Annotation
1 | //指向BlueDot的Weak指针 |
通过AnnotationView获得
通过 mapView: didAddAnnotationViews: 直接获得AnnotationView
1 | //指向BlueDotView的Weak指针 |
位置比较
位置比较可以直接比较Frame,但是在不同Scale下,并不是太稳定,所以选择通过CGPoint的位置反推Coordinate,然后通过CLLocationDistance来确定两者是否重合
1 | - (void)autoCorrectLocationOffset { |
纠偏策略
由于自动纠偏探测依赖于不稳定的ViewTree,所以很可能出现在卡顿的时候自动纠偏方法被连续调用两次(多出现于旧款iPad),所以需要制定一个可靠的纠偏策略,目前采用的策略:
- 在地图RegionChange时检查是否纠偏
- 在新的AnnotationView出现在MapView上时检测是否纠偏
- 通过拦截手势在用户操作时触发
存在问题
- 地图加载完毕后BlueDotView并不一定会出现在地图上,所以需要手动控制地图Zoom到某个Region保证BlueDotView出现
- BlueDotView闪现,可能会导致多次调用
小技巧
BlueDot的AnnotationView虽然不一定会出现在MapView上,但是不管MapView.showUser = ?多少,MapView的用户Annotation对象 MKUserLocation 永远会存在于地图上
如果想使用自己的Image来作为用户的AnnotationView,可以不再一开始就隐藏MapView.showUser,使用其作为参考点后再设置隐藏,因为BlueDotView实际被Add到MapView上时,并未进入Screen范围
用户的AnnotationView与BlueDotView时,实际是存在自己的AnnotationView的,可以采用赋值Image为nil的形式让其以透明样式存在