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
}