我有一个名为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的图像,显示大部分内存来自笔尖加载
此刻我没有任何要缓存的内容。视图基本上是一个scrollview,里面有mapview,还有一些标签和几个表视图。表视图没有填充任何内容,除了滚动视图的背景图像之外,我没有在视图中加载任何图像,但是当视图显示时,它应该被释放。
答案 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];
为了更好地帮助我需要知道如何启动表格以及其他功能。