单视图 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 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章