MKMapView释放内存

5

我已经遵循了若干SO问题中提供的建议,比如这个,为了释放MKMapView占用的内存 - 下面是我的代码

- (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的内存分配记录。
两个红旗(代际)表示我在模态视图控制器中显示MKMapView之前和之后的状态。 MKMapView似乎被释放了。例如,如果我在Instruments中过滤MKMapView的统计堆栈,则对象确实会在模态视图呈现时出现,并在关闭模态视图后消失。然而,在关闭地图视图后,我仍然有30多MB的内存没有被释放。
第二个红旗(B代际)数据显示有大量的对象(和非对象)持有这些内存。
当我查看其中一个实例的详细信息时,通常会显示一个堆栈跟踪,其中包含我猜与地图绘制相关的私有类。 有人知道如何释放所有这些数据吗?是否有某个缓存可以/应该清除?

你是否成功解决了这个问题? - nsinvocation
很遗憾,还没有。 - artooras
现在清除内存有什么进展了吗? - sridvijay
唉。有一次我也将 self.locationManager 设置为 nil,似乎有所帮助,但实际上并没有——内存仍然被分配了。 - artooras
2个回答

1

我的应用程序使用选项卡视图控制器来控制地图视图控制器,在静态变量中存储了对 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相同的大小,并且由于使用了自动布局,因此_mapView的框架大小完全受到addConstraints中设置的约束的控制(顶部、底部、左侧和右侧均等于_mapView.superview)。

我发现在viewDidDisppear:中从地图中删除标注,并在viewDidAppear中重新添加它们是强制性的。在viewDidDisppear:中取消设置_mapView.delegate并在viewDidAppear中重新设置可能更加清晰。

顺便说一下:静态变量_mapView仍然具有前导下划线,因为它是在IB中定义MKMapView时设置的实例变量。


0

这是我使用的解决方案,它运行良好。我认为这个问题最近才出现,因为在同一个项目中,我以前没有遇到地图正确释放的问题。

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

if let existingMapView = LocationSingleton.sharedInstance.singletonMapView {

    //Display map
}else{

    let newMapView = //Instantiate new map view controller
    LocationSingleton.sharedInstance.singletonMapView = newMapView

    //Display map
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接