没有为带有ARC的MKMapView发布内存

时间:2013-05-07 13:13:25

标签: ios memory ios6 mkmapview

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

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

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

显示视图时,只有1 ActivityDetailView和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

此刻我没有任何要缓存的内容。视图基本上是一个scrollview,里面有mapview,还有一些标签和几个表视图。表视图没有填充任何内容,除了滚动视图的背景图像之外,我没有在视图中加载任何图像,但是当视图显示时,它应该被释放。

3 个答案:

答案 0 :(得分:22)

事实证明,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的一个实例,这应该有助于最小化每次显示视图时分配的内存量,因为已经分配了地图视图。 / p>

答案 1 :(得分:0)

这不是从nib文件创建自定义视图的最佳方法。我建议你做的是将你从.nib文件中获取的视图作为子视图添加到self。代码看起来应该是这样的。

-(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 addSubview:xibView]; // This is where I have changed your code
    }
    return self;
}

答案 2 :(得分:0)

您可能遇到缓存问题。

如果你使用了很多图像,可能一个很好的选择是从xib中删除这些图像并使用代码添加它。或者,如果您使用[UIImage imageNamed:@""]

加载图片

但是使用类似的东西:

NSData* dataImg = [NSData dataWithContentsOfFile:@"yourfile.png"];
UIImage* img = [UIImage imageWithData:dataImg];

为了更好地帮助我需要知道如何启动表格以及其他功能。