Сохранение ресурсов с высоким разрешением, чтобы приложение знало, что может использовать их на устройствах Retina.

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

Я попробовал это с кодом ниже. Единственная проблема заключается в том, что изображения хранятся в папке «Документы», и приложение не распознает их как изображения Retina.

UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.test.com/[email protected]"]]];
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pngFilePath = [NSString stringWithFormat:@"%@/[email protected]",docDir];
NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(image)];
[data1 writeToFile:pngFilePath atomically:YES];

Как я должен сохранять изображения, чтобы приложение могло их использовать?


person aLFaRSi    schedule 04.02.2013    source источник


Ответы (3)


Метод imageWithData: всегда будет создавать изображение с масштабом 1,0 (не сетчатка). Для создания UIImage с поддержкой сетчатки из пользовательского местоположения за пределами пакета вам необходимо использовать метод initWithCGImage:scale:orientation::

UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.test.com/[email protected]"]]];
UIImage *retinaImage = [UIImage initWithCGImage:[image CGImage] scale:2.0 orientation:UIImageOrientationUp];

(и, очевидно, вы не должны загружать изображение синхронно...).

Мне нужно было сделать то же самое (загрузить зависящие от масштаба изображения из каталога документов) в моем последнем проекте, поэтому я написал небольшой удобный метод в категории UIImage:

- (id)initWithContentsOfResolutionIndependentFile:(NSString *)path
{
    if([[UIScreen mainScreen] scale] == 2.0) {
        NSString *path2x = [[path stringByDeletingLastPathComponent]
                            stringByAppendingPathComponent:[NSString stringWithFormat:@"%@@2x.%@",
                                                            [[path lastPathComponent] stringByDeletingPathExtension],
                                                            [path pathExtension]]];

        if([[NSFileManager defaultManager] fileExistsAtPath:path2x]) {
            return [self initWithCGImage:[[UIImage imageWithData:[NSData dataWithContentsOfFile:path2x]] CGImage] scale:2.0 orientation:UIImageOrientationUp];
        }
    }

    return [self initWithContentsOfFile:path];
}

Использование:

UIImage *myImage = [[UIImage alloc] initWithContentsOfResolutionIndependentFile:@"/path/to/image.png"];

Это попытается загрузить изображение из /path/to/[email protected] на сетчатке и использовать /path/to/image.png в противном случае.

person Daniel Rinser    schedule 04.02.2013

Это не работает, потому что источником изображений пользовательского интерфейса является папка Bundle, а не NSDocumentDirectory. Чтобы использовать изображения сетчатки и не сетчатки, вы должны определить, является ли устройство сетчаткой, и загрузить изображения программно из NSDocumentDirectory.

Вы можете использовать это для обнаружения сетчатки.

person djserva    schedule 04.02.2013
comment
И как я могу загрузить изображения из NSDocumentDirectory? - person aLFaRSi; 04.02.2013
comment
Используя свой код, добавьте UIImage *image = [UIImage imageWithContentsOfFile:pngFilePath];, где pngFilePath — путь к изображению. - person djserva; 04.02.2013
comment
@aLFaRSi Пожалуйста, смотрите мой ответ для примера и дальнейших комментариев. - person Daniel Rinser; 04.02.2013

Вы можете использовать [UIImage imageWithData: scale:] и иметь возможность пропустить соглашение об именах "@2x":

- (UIImage *)getRetinaSafeImage: (NSString *)fileName
{
    // alternatively you can use NSURL instead of path
    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSData *myImageData = [NSData dataWithContentsOfFile: [NSString stringWithFormat:@"%@/%@",docDir, fileName]];

    if([[UIScreen mainScreen] scale] == 2.0)
        return [UIImage imageWithData:myImageData scale:2.0];
    else return [UIImage imageWithData:myImageData];
}
person David Jirman    schedule 03.01.2014