MKMapView发布内存

为了从内存中释放MKMapView ,我遵循了几个SO问题中提供的建议,比如这个问题 – 我的代码如下

 - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; self.map.mapType = MKMapTypeHybrid; self.map.showsUserLocation = NO; self.map.delegate = nil; [self.map removeFromSuperview]; self.map = nil; self.locationManager.delegate = nil; } 

在某种程度上,它有效但不完全。 我来提供一些数据。

以下是Instruments的内存分配记录。

在此处输入图像描述

两个红色标记(Generations)表示我在模态视图控制器中显示MKMapView之前的状态以及我解除它之后的状态。 MKMapView似乎已被取消分配。 例如,如果我在Instruments for MKMapView过滤统计信息堆栈,则在呈现模态视图时确实会出现该对象,并且一旦关闭它就会消失。 但是,在解除了地图视图后,我仍然有30多MB的内存尚未被释放。

第B代(第二个红色标志)数据显示存在大量保存此内存的对象(和非对象)。

在此处输入图像描述

当我查看其中一个实例的扩展细节时,它通常会显示一个包含私有类的堆栈跟踪,我猜这些私有类与地图绘制有关 在此处输入图像描述

有谁知道如何释放所有数据? 我可以/应该清理一些缓存吗?

在我的应用程序中,它使用选项卡视图控制器控制下的地图视图控制器,我在一个静态变量中存储对MKMapView的引用,并反复使用同一个地图视图,而不是每次在ViewDidLoad中分配一个新的。 我的(部分)代码:

 @implementation PubMapViewController { NSMutableArray *annotations; } static MKMapView *_mapView = nil; - (void)viewDidLoad { [super viewDidLoad]; if (!_mapView) { _mapView = [[MKMapView alloc] init]; // frame set up with constraints } else { [_mapView removeAnnotations:_mapView.annotations]; // precaution } [_mapViewProxy addSubview:_mapView]; [self addConstraints:_mapView]; [self configureView:((PubTabBarController *)self.tabBarController).detailItem]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [_mapView addAnnotations:annotations]; if (annotations.count == 1) { [_mapView selectAnnotation:annotations[0] animated:YES]; } } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; [_mapView removeAnnotations:_mapView.annotations]; } 

这里, configureView:self.tabBarController.detailItem设置映射,设置其委托并将映射注释存储在变量annotations

地图成为界面构建器中定义的视图的子视图(实例变量@property (weak, nonatomic) IBOutlet UIView *mapViewProxy; )。 地图必须获得与mapViewProxy相同的大小,并且当我使用autolayout时,_mapView的帧大小完全使用addConstraints设置的约束(top,bottom,left和right等于_mapView.superview )来_mapView.superview

我发现必须从viewDidDisppear:的地图中删除注释viewDidDisppear:并将它们添加回viewDidAppear 。 在viewDidDisppear:取消设置_mapView.delegate可能会更加干净viewDidDisppear:并在viewDidAppear中将其设置回来。

BTW:静态变量_mapView仍然误导性_mapView有前导下划线,因为它是一个实例变量,之后通过在IB中定义MKMapView来设置。

这是我使用的解决方案,它工作正常。 我认为这个问题最近才引入,因为我在同一个项目中没有正确地解除分配问题。

我将地图实例存储在单例中,并在创建新实例之前检查它是否存在。 即:

 if let existingMapView = LocationSingleton.sharedInstance.singletonMapView { //Display map }else{ let newMapView = //Instantiate new map view controller LocationSingleton.sharedInstance.singletonMapView = newMapView //Display map }