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

OK、コードに戻りましょう。他のポスターが言ったように、自動解放プールが必要です。

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

NSAutoreleasePoolを使用します。コードをautoreleasepool内に保持します。

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

    ......
    ......
    [pool drain];
}
于 2012-07-06T09:32:29.523 に答える
0

forループを自動解放プールに入れます。

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