没有为带有 ARC 的 MKMapView 释放内存

2023-11-24

我有一个习惯UIView called ActivityDetailView我实例化然后添加到父视图控制器内的滚动视图。当分配此自定义视图时,每次额外的内存都会占用大约 1mb,并且 Instruments 显示内存永远不会被释放,即使视图和父视图控制器都有各自的内存dealloc被调用的方法。我收到内存警告,并且该应用程序最终被杀死,所以我显然做错了什么。

更新了有关地图视图的信息,但我需要修复

定制内ActivityDetailViewnib 文件中,有一个缩放并以用户位置为中心的地图视图。当我从笔尖中删除此地图视图以便它不会在屏幕上绘制时,内存分配问题就消失了。但是,我显然需要地图视图。为什么当地图视图超出范围时,地图视图的数据不会被释放?

只有 1 个ActivityDetailView and 1 ActivityDetailViewController当视图显示时还活着。一旦我将视图从堆栈中弹出,它们就不再存在。即使对象被杀死(如仪器所示),内存如何持续增长是没有意义的。如果父视图被释放,为什么地图视图数据没有被释放?

我做错了什么或者我应该检查什么?

这是自定义视图:

@interface ActivityDetailView ()
{
    CLLocation *location;
    __weak id parentViewController;
    int scrollViewX;

    ImageUtility *imageUtility;
}
@end

@implementation ActivityDetailView

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        NSArray *xibViews = [[NSBundle mainBundle] loadNibNamed:@"ActivityDetailView" owner:nil options:nil];
        if ([xibViews count] < 1) return nil;
        ActivityDetailView * xibView = [xibViews objectAtIndex:0];
        [xibView setFrame:frame];
        self = xibView;
    }
    return self;
}

- (id)initWithLocation:(CLLocation *)loc parentController:(id)parent
{
    self = [self initWithFrame:CGRectMake(0, 0, 320, 1000)];
    if (self)
    {
        imageUtility = [ImageUtility sharedManager];

        location = loc;
        parentViewController = parent;
        scrollViewX = 0;

        [self centerMapForActivityLocation];
        [self addPhotoButtonWithImageNamed:@"addActivityPhoto.png" target:parentViewController selector:@selector(addPhotoToActivity:)];
    }
    return self;
}

- (void)dealloc
{
    NSLog(@"ActivityDetailView was dealloced");
}

在父视图控制器中:

@interface ActivityDetailViewController ()
{
    ActivityDetailView *detailView;
}
@end

@implementation ActivityDetailViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Some code left out for clarity

    [self setupView];
}

- (void)didReceiveMemoryWarning
{
    NSLog(@"Purging image cache");
    [[ImageUtility sharedManager] purgeCache];
}

- (void)dealloc
{
    // These essentially do nothing to help the problem
    detailView.mapView = nil;
    [detailView removeFromSuperview];
    detailView = nil;
    self.scrollView = nil;

    NSLog(@"ActivityDetailViewController was dealloced");
}

- (void)setupView
{    
    // Add the activity detail view to the scroll view
    detailView = [[ActivityDetailView alloc] initWithLocation:self.activityLocation parentController:self];
    [self.scrollView addSubview:detailView];
    self.scrollView.contentSize = detailView.frame.size;

    // Setup the map view
    detailView.mapView.delegate = self;
    MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
    annotation.coordinate = self.activityLocation.coordinate;
    [detailView.mapView addAnnotation:annotation];
    if (self.activity.mapImageName) {
        detailView.mapView.scrollEnabled = YES;
        detailView.mapView.zoomEnabled = YES;
    } else {
        detailView.mapView.scrollEnabled = NO;
        detailView.mapView.zoomEnabled = NO;
    }

    // Add the weather area to the view
    dayView = [[DailyButtonView alloc] initWithFrame:CGRectMake(0, -17, 60, 70)];
    dayView.hidden = YES;
    [detailView.weatherView addSubview:dayView];
}

这是来自 Instruments 的图像,显​​示大部分内存来自笔尖加载

Instruments screenshot

我目前没有任何可缓存的内容。该视图基本上是一个滚动视图,内部有一个地图视图、一些标签和几个表格视图。表视图没有填充任何内容,除了滚动视图的背景图像之外,我没有在视图中加载任何图像,但是当视图加载时应该释放它。


事实证明,iOS 6 有一个已知的错误MKMapView没有正确释放它的内存。不幸的是,除了尝试强制地图视图清除其缓存之外,没有真正的修复方法,这对释放内存没有太大影响。

奇怪的是,即使应用程序收到内存警告,地图视图缓存仍然没有被正确清除。最终,应用程序变得不稳定并被操作系统杀死。

苹果最近的测试变得非常草率。这是第二个错误MKMapView我遇到过(另一个是mapViewDidFinishLoadingMap:被提前调用),如果他们刚刚做了一些性能和健全性测试,这两个错误就很容易被发现。

这是一些可能有帮助的代码:

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];

    // This is for a bug in MKMapView for iOS6
    [self purgeMapMemory];
}

// This is for a bug in MKMapView for iOS6
// Try to purge some of the memory being allocated by the map
- (void)purgeMapMemory
{
    // Switching map types causes cache purging, so switch to a different map type
    detailView.mapView.mapType = MKMapTypeStandard;
    [detailView.mapView removeFromSuperview];
    detailView.mapView = nil;
}

您可以做的另一件事是使用一个实例MKMapView在整个应用程序中,这应该有助于最大限度地减少每次显示视图时分配的内存量,因为地图视图已经被分配了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

没有为带有 ARC 的 MKMapView 释放内存 的相关文章

随机推荐