单视图 IOS 7 内存泄漏

Posted

技术标签:

【中文标题】单视图 IOS 7 内存泄漏【英文标题】:Single View IOS 7 Memory Leak 【发布时间】:2014-08-25 17:38:08 【问题描述】:

我正在尝试编写一个简单的 ios7 单视图应用程序。视图控制器有一个占据整个屏幕的 UI 图像视图,两个按钮占据了整个屏幕的左侧和右侧。本质上,我希望能够通过单击右侧滚动查看下一张连续图像,点击左侧查看前一张连续图像。

此应用程序有效,但我的按钮代码中的指针似乎没有被取消引用。或者别的什么,我不太确定。每次我进入新页面时,都会堆积越来越多的内存,直到它以超过 700mb RAM 运行。请帮助我更好地理解这个内存分配问题。运行项目配置文件后,似乎所有内存都被“All Anonymous VM”使用

这是视图控制器的代码。

#import "ABCViewController.h"
#import "ABCPage.h"

@interface ABCViewController ()

@end

@implementation ABCViewController

int current = 0;

- (void)viewDidLoad

[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ABCPage *A = [[ABCPage alloc] init];
A.picture = [UIImage imageNamed:@"a.png"];
ABCPage *B = [[ABCPage alloc] init];
B.picture = [UIImage imageNamed:@"b.png"];
ABCPage *C = [[ABCPage alloc] init];
C.picture = [UIImage imageNamed:@"c.png"];
ABCPage *E = [[ABCPage alloc] init];
E.picture = [UIImage imageNamed:@"e.png"];
ABCPage *F = [[ABCPage alloc] init];
F.picture = [UIImage imageNamed:@"f.png"];
ABCPage *G = [[ABCPage alloc] init];
G.picture = [UIImage imageNamed:@"g.png"];
ABCPage *H = [[ABCPage alloc] init];
H.picture = [UIImage imageNamed:@"h.png"];
ABCPage *I = [[ABCPage alloc] init];
I.picture = [UIImage imageNamed:@"i.png"];
ABCPage *J = [[ABCPage alloc] init];
J.picture = [UIImage imageNamed:@"j.png"];
ABCPage *K = [[ABCPage alloc] init];
K.picture = [UIImage imageNamed:@"k.png"];
ABCPage *L = [[ABCPage alloc] init];
L.picture = [UIImage imageNamed:@"l.png"];
ABCPage *M = [[ABCPage alloc] init];
M.picture = [UIImage imageNamed:@"m.png"];
ABCPage *N = [[ABCPage alloc] init];
N.picture = [UIImage imageNamed:@"n.png"];
ABCPage *O = [[ABCPage alloc] init];
O.picture = [UIImage imageNamed:@"o.png"];
ABCPage *P = [[ABCPage alloc] init];
P.picture = [UIImage imageNamed:@"p.png"];
ABCPage *Q = [[ABCPage alloc] init];
Q.picture = [UIImage imageNamed:@"q.png"];
ABCPage *R = [[ABCPage alloc] init];
R.picture = [UIImage imageNamed:@"r.png"];
ABCPage *S = [[ABCPage alloc] init];
S.picture = [UIImage imageNamed:@"s.png"];
ABCPage *T = [[ABCPage alloc] init];
T.picture = [UIImage imageNamed:@"t.png"];
ABCPage *U = [[ABCPage alloc] init];
U.picture = [UIImage imageNamed:@"u.png"];
ABCPage *V = [[ABCPage alloc] init];
V.picture = [UIImage imageNamed:@"v.png"];
ABCPage *W = [[ABCPage alloc] init];
W.picture = [UIImage imageNamed:@"w.png"];
ABCPage *X = [[ABCPage alloc] init];
X.picture = [UIImage imageNamed:@"x.png"];
ABCPage *Y = [[ABCPage alloc] init];
Y.picture = [UIImage imageNamed:@"y.png"];


self.myBook = [[NSMutableArray alloc] init];
[self.myBook addObject:A];
[self.myBook addObject:B];
[self.myBook addObject:C];
[self.myBook addObject:E];
[self.myBook addObject:F];
[self.myBook addObject:G];
[self.myBook addObject:H];
[self.myBook addObject:I];
[self.myBook addObject:J];
[self.myBook addObject:K];
[self.myBook addObject:L];
[self.myBook addObject:M];
[self.myBook addObject:N];
[self.myBook addObject:O];
[self.myBook addObject:P];
[self.myBook addObject:Q];
[self.myBook addObject:R];
[self.myBook addObject:S];
[self.myBook addObject:T];
[self.myBook addObject:U];
[self.myBook addObject:V];
[self.myBook addObject:W];
[self.myBook addObject:X];
[self.myBook addObject:Y];

self.imageView.image = A.picture;



- (void)didReceiveMemoryWarning

[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.


- (IBAction)previousButton:(UIButton *)sender


if (current > 0) 
current--;
ABCPage *currentPage = [self.myBook objectAtIndex:current];
self.imageView.image = currentPage.picture;




- (IBAction)nextButton:(UIButton *)sender

if (current < 23) 
current++;
ABCPage *currentPage = [self.myBook objectAtIndex:current];
self.imageView.image = currentPage.picture;



@end

【问题讨论】:

您正在一次创建和加载所有图像。你期望会发生什么?你觉得这段内存应该怎么释放? 首先,简化您的方法,例如 self.myBook = [[NSMutableArray alloc] initWithObjects:A,B,..., nil]; @Abizem 如何更正确地创建和加载图像? 【参考方案1】:

它的工作方式是,只要将 ABCPage 放入 myBook 数组,该数组就会在 ABCPage 上 +1;这个“保留”将停止对象被释放。您的页面引用了一个图像,因此该图像不会被释放。此外,当您将页面图像分配给 self.imageView 时,它会在设置期间变为 +2。

如果我没记错的话,你需要告诉持有图像视图的视图它需要更新

[self.view setNeedsDisplay]

否则屏幕不会显示新图像。

匿名 VM 内存变高的原因是,对于每个 UIImage,VM 子系统都会分配一个对等内存区域来“备份”包含图像数据的内存的图像。当 UIImage 被释放时,对端内存被释放。

在保持质量和速度平衡的同时进行调整以减少内存是很棘手的。我建议首先在每次需要时加载图像来尝试它,并且没有预先存储它们的数组。这意味着您将在浏览时对每张图像进行 +1 和 -1 处理。每次页面更改后,我也会发出 setNeedsDisplay 。您需要先解决内存泄漏问题,然后再从那里着手。

听起来图像太大而无法存储,因此您当前所在页面附近的图像可能需要缓存。这可能是您的下一步。

【讨论】:

【参考方案2】:

您可以为此使用带有自定义单元格的 UICollectionView,它对于这种特定情况会更好。

UICollectionViews 有一些称为可重用单元的东西,这意味着它不会保留在未使用的内存单元中。并且它会在可能的情况下重用现有的。它只会在必要时创建新的。

UICollectionView 具有与 UITableView 类似的工作方式,这是非常笼统的。

查看 UICollectionView 的文档,即使您可以进一步往下添加滑动手势识别器到您的应用程序,这是在水平排列的视图之间切换的常用方法。

https://developer.apple.com/library/ios/documentation/uikit/reference/UICollectionView_class/Reference/Reference.html

与您的内存泄漏有关,只需将 ABCPage *currentPage 设为属性,而不是在下一个和上一个中每次都实例化它。在您的类声明中将其设为一个属性,并在您执行 ABCPage *currentPage 时分配它,您正在创建新实例,并且您所提到的这些实例并未从内存中释放。

【讨论】:

以上是关于单视图 IOS 7 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

iOS 从 nib 加载视图会造成内存泄漏?

iOS4 调用 ImageNamed:仍然泄漏或导致内存问题?

iOS - 自定义 segue 内存泄漏

无法解释的内存泄漏 swift iOS

iOS 或 MonoTouch 中的固有内存泄漏?

Swift 表格视图,在表格视图单元格中播放视频,内存泄漏