1

我的应用程序在 UIImageView 内分配并显示图像。这发生在 viewDidLoad 的 24 个 imageViews 上。这些图像是从 50 个图像的列表中随机分配的。视图控制器从主屏幕被推送到模态。第一次加载需要一段时间。如果我很幸运,该视图会第二次加载。第三次,它几乎总是崩溃。我尝试将图像大小调整为 200 像素左右。我尝试使用以下方式分配图像:

    image1 = [UIImage imageNamed:@"image1.png"];

    [self.imageView setImage: image1];

还有:

    NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"image1" ofType:@"png"];

    image1 = [[UIImage alloc] initWithContentsOfFile:imagePath];

这第二个似乎只会让事情变得更糟。

我还尝试使用 Instruments 运行该应用程序,它无法识别任何内存泄漏。

我真的不知道还能去哪里。这个应用程序代表了巨大的时间投资,我真的很想看到这个问题得到解决......非常感谢

4

2 回答 2

2

从磁盘加载较小版本图像的最有效方法是:不使用imageNamed:,而是使用 Image I/O 框架通过调用CGImageSourceCreateThumbnailAtIndex. 这是我书中的例子:

NSURL* url =
    [[NSBundle mainBundle] URLForResource:@"colson"
                            withExtension:@"jpg"];
CGImageSourceRef src =
    CGImageSourceCreateWithURL((__bridge CFURLRef)url, nil);
CGFloat scale = [UIScreen mainScreen].scale;
CGFloat w = self.iv.bounds.size.width*scale;
NSDictionary* d =
    @{(id)kCGImageSourceShouldAllowFloat: (id)kCFBooleanTrue,
     (id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue,
     (id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue,
     (id)kCGImageSourceThumbnailMaxPixelSize: @((int)w)};
CGImageRef imref =
    CGImageSourceCreateThumbnailAtIndex(src, 0, (__bridge CFDictionaryRef)d);
UIImage* im =
    [UIImage imageWithCGImage:imref scale:scale
                  orientation:UIImageOrientationUp];
self.iv.image = im;
CFRelease(imref); CFRelease(src);

要求 UIImageView 显示比 UIImageView 本身更大的图像是一种巨大的内存浪费,因为全尺寸图像的位图必须保存在内存中。Image I/O 框架生成较小的版本,甚至无需将整个原始图像作为位图解压缩到内存中。

于 2013-02-22T03:01:33.803 回答
1

我曾经遇到过这个问题,来自常规网站的图像比我使用的视图大得多。如果我没记错的话,这些图像正在被解压缩到它们的全分辨率,然后适合图像视图,这会占用你的内存。在显示它们之前,我必须先将它们缩小到图像视图大小。添加 CoreGraphics.framework 并使用此类创建一个图像对象以与您的图像视图一起使用。我在网上找到了它并对其进行了一些调整以寻找相同的答案,但不记得在哪里,所以感谢发布原件的那个人,无论他们是谁。

ImageScale.h

#import <Foundation/Foundation.h>

@interface ImageScale : NSObject

+ (UIImage*)imageWithImage:(UIImage*)sourceImage scaledToSize:(CGSize)newSize;

@end

ImageScale.m

#import "ImageScale.h"

@implementation ImageScale

+ (UIImage*)imageWithImage:(UIImage*)sourceImage scaledToSize:(CGSize)newSize
{
    CGFloat targetWidth = newSize.width;
    CGFloat targetHeight = newSize.height;

    CGImageRef imageRef = [sourceImage CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    if (bitmapInfo == kCGImageAlphaNone) {
        bitmapInfo = kCGImageAlphaNoneSkipLast;
    }

    CGContextRef bitmap;

    if (sourceImage.imageOrientation == UIImageOrientationUp ||  sourceImage.imageOrientation == UIImageOrientationDown) {
        bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    } else {
        bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    }

    if (sourceImage.imageOrientation == UIImageOrientationLeft) {
        CGContextRotateCTM (bitmap, M_PI_2); // + 90 degrees
        CGContextTranslateCTM (bitmap, 0, -targetHeight);

    } else if (sourceImage.imageOrientation == UIImageOrientationRight) {
        CGContextRotateCTM (bitmap, -M_PI_2); // - 90 degrees
        CGContextTranslateCTM (bitmap, -targetWidth, 0);

    } else if (sourceImage.imageOrientation == UIImageOrientationUp) {
        // NOTHING
    } else if (sourceImage.imageOrientation == UIImageOrientationDown) {
        CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
        CGContextRotateCTM (bitmap, -M_PI); // - 180 degrees
    }

    CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return newImage; 
}

@end
于 2013-02-22T02:42:32.587 回答