Iphone 从文档目录读取图像时内存泄漏
我在循环中读取文档目录中的图像Iphone 从文档目录读取图像时内存泄漏,iphone,Iphone,我在循环中读取文档目录中的图像 for(iArrCount=0;iArrCount<[arrImages count];iArrCount++) { UIButton *btnImage = [UIButton buttonWithType:UIButtonTypeCustom]; btnImage.frame = CGRectMake(xRow, yRow, width, height); [btnImage addTarget:s
for(iArrCount=0;iArrCount<[arrImages count];iArrCount++)
{
UIButton *btnImage = [UIButton buttonWithType:UIButtonTypeCustom];
btnImage.frame = CGRectMake(xRow, yRow, width, height);
[btnImage addTarget:self action:@selector(imageDetails:) forControlEvents:UIControlEventTouchUpInside];
btnImage.tag = iCount;
if(iCount<[arrImages count])
{
NSString *workSpacePath=[[self applicationDocumentsDirectory] stringByAppendingPathComponent:[arrImages objectAtIndex:iCount]];
[btnImage setBackgroundImage:[UIImage imageWithData:[NSData dataWithContentsOfFile:workSpacePath]] forState:UIControlStateNormal];
[scrollImages addSubview:btnImage];
}
}
for(iArrCount=0;iArrCount将您的for
循环放入自动释放池:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for(...)
{
....
}
[pool release];
使用。将代码保存在自动释放池中
for(iArrCount=0;iArrCount<[arrImages count];iArrCount++)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
......
......
[pool drain];
}
for(iArrCount=0;iArrCount问题在于,您的按钮正在维护对全分辨率图像的引用。您需要做的是将图像缩小到按钮尺寸,并将缩小后的图像设置为按钮背景。类似这样的操作应该可以做到:
在UIImage上创建一个类别…我们称之为UIImage+Scaler.h
// UIImage+Scaler.h
#import <UIKit/UIKit.h>
@interface UIImage (Scaler)
- (UIImage*)scaleToSize:(CGSize)size;
@end
好的,现在回到你的代码。就像其他海报上说的那样,你需要一个自动释放池
CGSize buttonSize = CGSizeMake(width, height);
for(iArrCount=0;iArrCount<[arrImages count];iArrCount++)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
UIButton *btnImage = [UIButton buttonWithType:UIButtonTypeCustom];
btnImage.frame = CGRectMake(xRow, yRow, width, height);
[btnImage addTarget:self
action:@selector(imageDetails:)
forControlEvents:UIControlEventTouchUpInside];
btnImage.tag = iCount;
if(iCount<[arrImages count])
{
NSString *workSpacePath=[[self applicationDocumentsDirectory]
stringByAppendingPathComponent:
[arrImages objectAtIndex:iCount]];
UIImage* bigImage = [UIImage imageWithData:[NSData
dataWithContentsOfFile:workSpacePath]];
UIImage* smallImage = [bigImage scaleToSize:buttonSize];
[btnImage setBackgroundImage:smallImage forState:UIControlStateNormal];
[scrollImages addSubview:btnImage];
}
[pool drain]; // must drain pool inside loop to release bigImage
}
CGSize按钮大小=CGSizeMake(宽度、高度);
对于(iArrCount=0;iArrCount仍在崩溃。我发现了一件事。我注释掉了行[btn setBackgroundImage]并分配了一个资源图像。但我没有注释掉从文档目录中读取文件的行。应用程序没有崩溃。嗯,似乎图像很大,因此它需要巨大的内存。这就是它崩溃的原因。我认为你应该重新使用按钮,就像我们正在使用tablecell一样。仍然崩溃。我发现一件事。我同意注释掉了行[btn setBackgroundImage]并分配了一个资源映像。但我没有注释掉从文档目录读取文件的行。应用程序没有崩溃。请检查[NSData DATA WITH CONTENTS OFFILE:workSpacePath]中发生的情况
您也可以使用分派应用程序而不是for循环,并从主队列中获取所有工作。然后,当将按钮添加到滚动视图时,通过主队列分派该方法。这样我们就不会在加载图像时阻塞主线程。@timthetoolman很好的建议!您还可以缓存缩小的图像(持续)并仅为新图像计算它们…但由于OP正在努力解决一些基本的内存管理问题,因此最好不要使问题变得太复杂;-)
CGSize buttonSize = CGSizeMake(width, height);
for(iArrCount=0;iArrCount<[arrImages count];iArrCount++)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
UIButton *btnImage = [UIButton buttonWithType:UIButtonTypeCustom];
btnImage.frame = CGRectMake(xRow, yRow, width, height);
[btnImage addTarget:self
action:@selector(imageDetails:)
forControlEvents:UIControlEventTouchUpInside];
btnImage.tag = iCount;
if(iCount<[arrImages count])
{
NSString *workSpacePath=[[self applicationDocumentsDirectory]
stringByAppendingPathComponent:
[arrImages objectAtIndex:iCount]];
UIImage* bigImage = [UIImage imageWithData:[NSData
dataWithContentsOfFile:workSpacePath]];
UIImage* smallImage = [bigImage scaleToSize:buttonSize];
[btnImage setBackgroundImage:smallImage forState:UIControlStateNormal];
[scrollImages addSubview:btnImage];
}
[pool drain]; // must drain pool inside loop to release bigImage
}