代码改变世界

iOS MKMapView 优化内存占用

2018-11-23 11:17  PingKang  阅读(1063)  评论(0编辑  收藏  举报

 

1、相信很多小伙伴都在app内用过地图模块 ,可能是第三方的(如:百度,高德等),但是第三方的地图不如原生的界面清晰度高,也没有原生的界面渲染的速度快,这也从侧面反应出原生的mapview占用内存高的一个原因了

2、相信很多的人都用app中发现,只有导航类的APP才会把内嵌mapview的Viewcontroller作为首页,其他的APP都不会这么做,当然导致这种现象的主要原因可以归结于业务需求导致,但是小不分原因是因为mapview的内存占用是在是太高,导致APP内剩余业务所能使用的内存急剧的减少,最后导致进入其他业务模块会出现闪退的情况。

3、言归正传,到底怎么才能优化mapview在APP中的内存占用情况呢

  • 相信很多人查到的情况都是类似于 先把mapview移除,然后再做添加 如下操作:
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
    [mapView removeFromSuperview];
    [self.view addSubview:mapView];
} 

 对于用这种方法,内存的占用情况如下图

 

也不能说这种操作无效,因为mapview在滑动的时候,确实有内存的减少,但是对于将mapview作为app的首页进行内嵌显示的时候,这种优化显得很鸡肋,而且明显站不住脚,要知道上述操作从理论上来讲 ,对内存释放没有什么帮助,因为Viewcontroller是作为底部菜单存在的,那就会延伸出来本文的中心论点,怎么才能优化地图对内存的占用呢,那就是增加一个改变地图类型的方法 ,强制地图对内容进行重绘,此时在因为地图内容占用的内存就会得到释放

 

  • 增加改变地图类型的方法,并在上述方法中进行调用
- (void)applyMapViewMemoryRelease{
   
    MKMapType _type = _mapView.mapType;
    switch (_mapView.mapType) {
        case MKMapTypeHybrid:
        {
            _mapView.mapType = MKMapTypeStandard;
        }
            
            break;
        case MKMapTypeStandard:
        {
            _mapView.mapType = MKMapTypeHybrid;
        }
            
            break;
        default:
            break;
    }
    _mapView.mapType = _type;
}

调用方式

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
    [self applyMapViewMemoryRelease];
    [mapView removeFromSuperview];
    [self.view addSubview:mapView];
}

运行以后,测试内存的占用情况,如下图

但是这种方法会有一个额外的副作用,就是在滑动地图的时候,地图会先闪现空白的网格,然后才会加载地图,而且地图的加载速度依赖于网络速度,所以就会增加如下的优化建议,怎么在地图移动或者缩放到一定的级别以后 ,再修改地图的类型,那就需要对上述方法进行改造,如下:

- (void)applyMapViewMemoryRelease{
    //其中 mapRegionSpan 是一个全局变量
    if (self.mapView.region.span.longitudeDelta < 0.005 || self.mapView.region.span.latitudeDelta < 0.005) {
        return;
    }
    
    float longitudeDelta = self.mapView.region.span.longitudeDelta - mapRegionSpan.longitudeDelta;
    float latitudeDelta = self.mapView.region.span.latitudeDelta - mapRegionSpan.latitudeDelta;
    
    if ( fabs(longitudeDelta) < 0.00005 && fabs(latitudeDelta) <0.00005) {
        return;
    }
    
    MKMapType _type = _mapView.mapType;
    switch (_mapView.mapType) {
        case MKMapTypeHybrid:
        {
            _mapView.mapType = MKMapTypeStandard;
        }
            
            break;
        case MKMapTypeStandard:
        {
            _mapView.mapType = MKMapTypeHybrid;
        }
            
            break;
        default:
            break;
    }
    _mapView.mapType = _type;
    mapRegionSpan = self.mapView.region.span;
}

用以上方法就可以解决用户在滑动app,或者只是碰到地图以后 ,不会执行此方法的逻辑,也就不会显示网格了