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 }