iOS设备中的图像存储,适当的行为?

时间:2011-10-07 15:17:53

标签: iphone ios uitableview uiimage

对于我正在制作的应用程序,我对iOS设备中的图像存储感到满意。

我的要求是将一个Image加载到tableViewCell上,比如UITableViewCell的默认图像空间,因此不是背景图像。

现在,用户可以通过PhotoDirectory添加图像,也可以拍摄全新的图像。

如果拍摄了新图像,该图像应该优先存储在哪里?在默认的照片目录中?或者在应用程序沙箱的文档文件夹中?

因为这些是图像文件,我担心应用程序包中的商店图像会变得很大,我担心我不会超过尺寸限制。

虽然性能明智......什么是更好的选择?

1 个答案:

答案 0 :(得分:-1)

我有一个应用程序也可以完成你描述的一些事情。我的解决方案是创建一个我称之为imageStore的单例。您可以找到有关单身here

的信息

在这个imageStore中,我存储了所有“全尺寸”图像;但是,和你一样,我担心这些图像的大小,所以我使用缩略图而不是直接使用它们。我做的是这个。对于我想在表中表示的每个对象,我确保该对象具有一个UIImage,它定义为thumnail大小(64x64或您想要的任何大小)。然后创建一个对象,我创建一个与对象一起存储的缩略图。我使用这个缩略图代替较大的图像,我可以在其中使用它,就像在表格单元格上一样。

我目前不在我的Mac后面,但如果你愿意,我可以稍后发布一些代码来演示单例以及缩略图的创建和使用。

这是我的ImageStore头文件

#import <Foundation/Foundation.h>

@interface BPImageStore : NSObject {
    NSMutableDictionary *dictionary;
}

+ (BPImageStore *)defaultImageStore;

- (void)setImage:(UIImage *)i forKey:(NSString *)s;
- (UIImage *)imageForKey:(NSString *)s;
- (void)deleteImageForKey:(NSString *)s;

@end

这是ImageStore.m文件 - 我的Singleton

#import "BPImageStore.h"

static BPImageStore *defaultImageStore = nil;

@implementation BPImageStore

+ (id)allocWithZone:(NSZone *)zone {
    return [[self defaultImageStore] retain];
}

+ (BPImageStore *)defaultImageStore {
    if(!defaultImageStore) {
        defaultImageStore = [[super allocWithZone:NULL] init];
    }
    return defaultImageStore;
}

- (id)init
{

    if(defaultImageStore) {
        return defaultImageStore;
    }

    self = [super init];
    if (self) {
        dictionary = [[NSMutableDictionary alloc] init];
        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc addObserver:self selector:@selector(clearCach:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
    }

    return self;
}

- (void) clearCache:(NSNotification *)note {
    [dictionary removeAllObjects];
}

- (oneway void) release {
    // no op
}

- (id)retain {
    return self;
}

- (NSUInteger)retainCount {
    return NSUIntegerMax;
}

- (void)setImage:(UIImage *)i forKey:(NSString *)s {
    [dictionary setObject:i forKey:s];

    // Create full path for image
    NSString *imagePath = pathInDocumentDirectory(s);

    // Turn image into JPEG data
    NSData *d = UIImageJPEGRepresentation(i, 0.5);

    // Write it to full path
    [d writeToFile:imagePath atomically:YES];

}

- (UIImage *)imageForKey:(NSString *)s {
    // if possible, get it from the dictionary
    UIImage *result = [dictionary objectForKey:s];
    if(!result) {
        // Create UIImage object from file
        result = [UIImage imageWithContentsOfFile:pathInDocumentDirectory(s)];
        if (result)
            [dictionary setObject:result forKey:s];
    }
    return result;
}

- (void)deleteImageForKey:(NSString *)s {
    if(!s) {
        return;
    }
    [dictionary removeObjectForKey:s];
    NSString *path = pathInDocumentDirectory(s);
    [[NSFileManager defaultManager] removeItemAtPath:path error:NULL];
}

@end

这是我使用图像存储的地方。在我的对象“播放器”中,我有一个UIImage来存储缩略图,我有一个NSString来存放我创建的密钥。我放入商店的每张原始图片都有一把钥匙。我用我的播放器存储密钥。如果我需要原始图像,我会使用唯一的密钥。这里也值得注意的是,我甚至没有将原始图像存储为全尺寸,我已经将其缩小了一点。毕竟在我的情况下,它是一个玩家的照片,没有人看起来太好,以至于有一个完整的分辨率图片:))

 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSString *oldKey = [player imageKey];
    // did the player already have an image?
    if(oldKey) {
        // delete the old image
        [[BPImageStore defaultImageStore] deleteImageForKey:oldKey];
    }


    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    // Create a CFUUID object  it knows how to create unique identifier
    CFUUIDRef newUniqueID = CFUUIDCreate(kCFAllocatorDefault);

    // Create a string from unique identifier
    CFStringRef newUniqueIDString = CFUUIDCreateString(kCFAllocatorDefault, newUniqueID);

    // Use that unique ID to set our player imageKey
    [player setImageKey:(NSString *)newUniqueIDString];

    // we used Create in the functions to make objects, we need to release them
    CFRelease(newUniqueIDString);
    CFRelease(newUniqueID);

    //Scale the images down a bit
    UIImage *smallImage = [self scaleImage:image toSize:CGSizeMake(160.0,240.0)];


    // Store image in the imageStore with this key
    [[BPImageStore defaultImageStore] setImage:smallImage
                                        forKey:[player imageKey]];

    // Put that image onto the screen in our image view
    [playerView setImage:smallImage];

    [player setThumbnailDataFromImage:smallImage];
}

以下是返回从imageStore获取原始图像的示例:

// Go get image
NSString *imageKey = [player imageKey];
if (imageKey) {
    // Get image for image key from image store
    UIImage *imageToDisplay = [[BPImageStore defaultImageStore] imageForKey:imageKey];
    [playerView setImage:imageToDisplay];
} else {
    [playerView setImage:nil];
}

最后,这是我如何从原始图像创建缩略图:

- (void)setThumbnailDataFromImage:(UIImage *)image {
CGSize origImageSize = [image size];

CGRect newRect;
newRect.origin = CGPointZero;
newRect.size = [[self class] thumbnailSize]; // just give a size you want here instead

// How do we scale the image
float ratio = MAX(newRect.size.width/origImageSize.width, newRect.size.height/origImageSize.height);

// Create a bitmap image context
UIGraphicsBeginImageContext(newRect.size);

// Round the corners
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:newRect cornerRadius:5.0];

[path addClip];

// Into what rectangle shall I composite the image
CGRect projectRect;
projectRect.size.width = ratio * origImageSize.width;
projectRect.size.height = ratio *origImageSize.height;
projectRect.origin.x = (newRect.size.width - projectRect.size.width) / 2.0;
projectRect.origin.y = (newRect.size.height - projectRect.size.height) / 2.0;

// Draw the image on it
[image drawInRect:projectRect];

// Get the image from the image context, retain it as our thumbnail
UIImage *small = UIGraphicsGetImageFromCurrentImageContext();
[self setThumbnail:small];

// Get the image as a PNG data
NSData *data = UIImagePNGRepresentation(small);
[self setThumbnailData:data];

// Cleanup image context resources
UIGraphicsEndImageContext();

}