2

我正在循环读取文档目录中的图像。

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];
}
}  

这样做时,控制权进入didRecieveMemoryWarning应用程序崩溃。如果我用资源文件夹中的图像替换图像,应用程序不会崩溃。为什么这样?

4

3 回答 3

2

问题是您的按钮保持对全分辨率图像的引用。您需要做的是将图像按比例缩小到按钮尺寸,并将按比例缩小的图像设置为按钮背景。这样的事情应该可以解决问题:

在 UIImage 上创建一个类别...我们称之为 UIImage+Scaler.h

// UIImage+Scaler.h
#import <UIKit/UIKit.h>

@interface UIImage (Scaler)
- (UIImage*)scaleToSize:(CGSize)size;
@end

和实施:

// UIImage+Scaler.m
#import "UIImage+Scaler.h"

#define kBitsPerComponent 8
#define kBitmapInfo       kCGImageAlphaPremultipliedLast

- (UIImage*)scaleToSize:(CGSize)size
{
    CGBitmapInfo bitmapInfo = kBitmapInfo;
    size_t bytesPerRow = size.width * 4.0;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, size.width, 
                                   size.height, kBitsPerComponent, 
                                   bytesPerRow, colorSpace, bitmapInfo);

    CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
    CGContextDrawImage(context, rect, self.CGImage);

    CGImageRef scaledImageRef = CGBitmapContextCreateImage(context);
    UIImage* scaledImage = [UIImage imageWithCGImage:scaledImageRef];

    CGImageRelease(scaledImageRef);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);

    return scaledImage;
}

好的,现在回到你的代码。就像其他海报所说的那样,您需要一个自动释放池。

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
} 

希望这能解决问题。

于 2012-07-07T02:54:59.057 回答
0

将您的for循环放入自动释放池中:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for(...)
{
   ....
}
[pool release];
于 2012-07-06T09:29:56.623 回答
0

使用NSAutoreleasePool。将您的代码保存在自动释放池中。

for(iArrCount=0;iArrCount<[arrImages count];iArrCount++)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    ......
    ......
    [pool drain];
}
于 2012-07-06T09:32:29.523 回答