ios7 – 使用没有imageNamed的xbox来防止内存问题?

根据苹果文档,建议为iOS7应用程序使用xcassets,并通过imageNamed引用这些映像。

但是据我所知,imageNamed和内存总是有问题。

所以我做了一个简短的测试应用程序 – 使用imageNamed引用xcassets目录中的图像,并启动了分析器…结果如预期的那样。一旦分配的内存没有再次释放,即使我从超级视图中删除了ImageView并将其设置为nil。

我目前正在使用许多大图像的iPad应用程序,这种奇怪的imageView行为会导致内存警告。

但是在我的测试中,我无法通过imageWithContentsOfFile访问xcassets映像。

那么在iOS7上使用大图像的最佳方法是什么?有没有办法以另一种(更有效的方式)从xcassets目录中访问图像?或者我不应该使用xcassets,所以我可以使用imageWithContentsOfFile?

谢谢你的答案!

更新:缓存驱逐工作罚款(至少自iOS 8.3以来)。

我决定和苹果公司一起推出“新的Images.xboxets”。事情开始恶化,当我在应用程序和应用程序中有大约350MB的图像不断崩溃(在Retina iPad上;可能是因为加载的图像的大小)。

我写了一个非常简单的测试应用程序,我在三种不同的类型加载图像(观察分析器):

> imageNamed:从资产加载:图像永远不会被释放,应用程序崩溃(对我来说,我可以加载400张图像,但这取决于图像大小)
> imageNamed :(通常包含在项目中):内存使用率很高,而且有一段时间(> 400图像),我看到一个调用didReceiveMemoryWarning :,但应用程序运行正常。
> imageWithContentsOfFile([[NSBundle mainBundle] pathForResource:…):内存使用率非常低(< 20mb),因为图像一次只能加载一次。
我真的不会怪我的imageNamed:方法缓存的一切,因为缓存是一个好主意,如果你必须一次又一次的显示你的图像,但这是一种难过的苹果没有实现它的资产(或没有记录它没有实现)。在我的用例中,我将去使用非缓存imageWithData,因为用户不会再看到图像。

由于我的应用程序几乎是最终的,我非常喜欢使用加载机制来自动找到正确的图像,所以我决定使用它:

>我从project-target-copy-phase中删除images.xcasset,并将所有图像“再次”添加到项目和复制阶段(只需直接添加Images.xcassets的顶级文件夹,并确保“添加到目标xxx“被选中,并为任何添加的文件夹创建组(我没有打扰无用的Contents.json文件)。
>在第一次构建期间,如果多个图像具有相同的名称(并以一致的方式重命名它们),则检查新的警告。
>对于应用程序图标和启动映像,在项目目标一般中设置“不要使用资产目录”,并手动引用它们。
>我已经编写了一个shell脚本,以从所有的Contents.json文件生成一个json模型(让苹果在其资产访问代码中使用信息)

脚本:

cd projectFolderWithImageAsset
echo "{\"assets\": [" > a.json
find Images.xcassets/ -name \*.json | while read jsonfile; do
  tmppath=${jsonfile%.imageset/*}
  assetname=${tmppath##*/}
  echo "{\"assetname\":\"${assetname}\",\"content\":" >> a.json
  cat $jsonfile >> a.json; 
  echo '},' >>a.json
done
echo ']}' >>a.json

>删除最后一个“,”从json输出的逗号,因为我没有打扰手动这里做。
>我已经使用以下应用程序来生成json-model-access代码:https://itunes.apple.com/de/app/json-accelerator/id511324989?mt=12(当前免费),带前缀IMGA
>我已经写了一个很好的类别,使用方法swizzling为了不改变运行代码(并希望很快删除我的代码):

(实现不完整的所有设备和后备机制!!)

#import "UIImage+Extension.h"
#import <objc/objc-runtime.h>
#import "IMGADataModels.h"

@implementation UIImage (UIImage_Extension)


+ (void)load{
static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        Method imageNamed = class_getClassMethod(class, @selector(imageNamed:));
        Method imageNamedCustom = class_getClassMethod(class, @selector(imageNamedCustom:));
        method_exchangeImplementations(imageNamed, imageNamedCustom);
    });
}

+ (IMGABaseClass*)model {
    static NSString * const jsonFile = @"a";
    static IMGABaseClass *baseClass = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSString *fileFilePath = [[NSBundle mainBundle] pathForResource:jsonFile ofType:@"json"];
        NSData* myData = [NSData dataWithContentsOfFile:fileFilePath];
        __autoreleasing NSError* error = nil;
        id result = [NSJSONSerialization JSONObjectWithData:myData
                                                    options:kNilOptions error:&error];
        if (error != nil) {
            ErrorLog(@"Could not load file %@. The App will be totally broken!!!", jsonFile);
        } else {
            baseClass = [[IMGABaseClass alloc] initWithDictionary:result];
        }
    });
    return baseClass;
}


+ (UIImage *)imageNamedCustom:(NSString *)name{

    NSString *imageFileName = nil;
    IMGAContent *imgContent = nil;
    CGFloat scale = 2;

    for (IMGAAssets *asset in [[self model] assets]) {
        if ([name isEqualToString: [asset assetname]]) {
            imgContent = [asset content];
            break;
        }
    }
    if (!imgContent) {
        ErrorLog(@"No image named %@ found", name);
    }

    if (is4InchScreen) {
        for (IMGAImages *image in [imgContent images]) {
            if ([@"retina4" isEqualToString:[image subtype]]) {
                imageFileName = [image filename];
                break;
            }
        }
    } else {
        if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ) {
            for (IMGAImages *image in [imgContent images]) {
                if ([@"iphone" isEqualToString:[image idiom]] && ![@"retina4" isEqualToString:[image subtype]]) {
                    imageFileName = [image filename];
                    break;
                }
            }
        } else {
            if (isRetinaScreen) {
                for (IMGAImages *image in [imgContent images]) {
                    if ([@"universal" isEqualToString:[image idiom]] && [@"2x" isEqualToString:[image scale]]) {
                        imageFileName = [image filename];
                        break;
                    }
                }
            } else {
                for (IMGAImages *image in [imgContent images]) {
                    if ([@"universal" isEqualToString:[image idiom]] && [@"1x" isEqualToString:[image scale]]) {
                        imageFileName = [image filename];
                        if (nil == imageFileName) {
                            // fallback to 2x version for iPad unretina
                            for (IMGAImages *image in [imgContent images]) {
                                if ([@"universal" isEqualToString:[image idiom]] && [@"2x" isEqualToString:[image scale]]) {
                                    imageFileName = [image filename];
                                    break;
                                }
                            }
                        } else {
                            scale = 1;
                            break;
                        }
                    }
                }
            }
        }
    }

    if (!imageFileName) {
        ErrorLog(@"No image file name found for named image %@", name);
    }

    NSString *imageName = [[NSBundle mainBundle] pathForResource:imageFileName ofType:@""];
    NSData *imgData = [NSData dataWithContentsOfFile:imageName];
    if (!imgData) {
        ErrorLog(@"No image file found for named image %@", name);
    }
    UIImage *image = [UIImage imageWithData:imgData scale:scale];
    DebugVerboseLog(@"%@", imageFileName);
    return image;
}

@end
http://stackoverflow.com/questions/22856283/use-xcassets-without-imagenamed-to-prevent-memory-problems

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:ios7 – 使用没有imageNamed的xbox来防止内存问题?