Хранение изображений на устройствах iOS, соответствующее поведение? - PullRequest
0 голосов
/ 07 октября 2011

Я немного озадачен хранением изображений на устройствах iOS для приложения, которое я создаю.

Мое требование - загрузить изображение в tableViewCell, скажем, в пространстве изображений по умолчанию UITableViewCell иследовательно, это не фоновое изображение.

Теперь пользователь может добавить изображение либо через PhotoDirectory, либо сделать совершенно новое изображение.

Если берется новое изображение, где должно храниться это изображениеpreferebly?В каталоге фотографий по умолчанию?или в папке с документами в изолированной программной среде приложения?

Поскольку это файлы изображений, я боюсь, что хранение изображений в комплекте приложений может сделать его довольно большим, боюсь, я не перейду предел размера.

Хотя производительность выше ... что было бы лучше?

1 Ответ

0 голосов
/ 07 октября 2011

У меня есть приложение, которое также выполняет некоторые вещи, которые вы описываете.Моим решением было создать синглтон, который я называю своим 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();

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...