1

[UIImage imageNamed:]バンドルからファイルをロードするときUIImageに、同じ画像の複数のインスタンスを防ぐためのキャッシュ、@ 2xと〜ipadのサフィックスの検索、scaleプロパティの正しい設定など、多くの巧妙なことを行います。ドキュメントディレクトリ(で指定)から画像をロードするときにも同じことができるようにしたいと思いますNSURL。私は周りを見回しましたが、これに関するドキュメントで何も見つかりません、私が見逃したものはありますか?

私は現在これを自分で実装しています(シバン全体、キャッシュなど)が、フレームワークコードを複製するのは嫌です。完了する前に回答を得たいと思っていますが、そうでない場合はコードを投稿します。

4

2 に答える 2

1

これは私が思いついた最高のものです。フレームワークで動作を複製するため(おそらく微妙な不整合があるため)理想的ではありませんが、私たちが望む素晴らしいことを実行しimageNamed:ます。

+ (UIImage*)imageNamed:(NSString*)name relativeToURL:(NSURL*)rootURL
{
    // Make sure the URL is a file URL
    if(![rootURL isFileURL])
    {
        NSString* reason = [NSString stringWithFormat:@"%@ only supports file URLs at this time.", NSStringFromSelector(_cmd)];
        @throw [NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil];
    }

    // Check the cache first, using the raw url/name as the key
    NSCache*    cache = objc_getAssociatedObject([UIApplication sharedApplication].delegate, @"imageCache");
    // If cache doesn't exist image will be nil - cache is created later only if everything else goes ok
    NSURL*      cacheKey = [rootURL URLByAppendingPathComponent:name];
    UIImage*    image = [cache objectForKey:cacheKey];
    if(image != nil)
    {
        // Return the cached image
        return image;
    }

    // Various suffixes to try in preference order
    NSString*   scaleSuffix[] =
    {
        @"@2x",
        @""
    };
    CGFloat     scaleValues[] =
    {
        2.0f,
        1.0f
    };
    NSString*   deviceSuffix[] =
    {
        ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) ? @"~ipad" : @"~iphone",
        @""
    };
    NSString*   formatSuffix[] =
    {
        @"png"
    };
    NSURL*      imageURL = nil;
    CGFloat     imageScale = 0.0f;

    // Iterate through scale suffixes...
    NSInteger   ss, ssStart, ssEnd, ssInc;
    if([UIScreen mainScreen].scale == 2.0f)
    {
        // ...forwards
        ssStart = 0;
        ssInc = 1;
    }
    else
    {
        // ...backwards
        ssStart = (sizeof(scaleSuffix) / sizeof(NSString*)) - 1;
        ssInc = -1;
    }
    ssEnd = ssStart + (ssInc * (sizeof(scaleSuffix) / sizeof(NSString*)));
    for(ss = ssStart; (imageURL == nil) && (ss != ssEnd); ss += ssInc)
    {
        // Iterate through devices suffixes
        NSInteger ds;
        for(ds = 0; (imageURL == nil) && (ds < (sizeof(deviceSuffix) / sizeof(NSString*))); ds++)
        {
            // Iterate through format suffixes
            NSInteger fs;
            for(fs = 0; fs < (sizeof(formatSuffix) / sizeof(NSString*)); fs++)
            {
                // Add all of the suffixes to the URL and test if it exists
                NSString*   nameXX = [name stringByAppendingFormat:@"%@%@.%@", scaleSuffix[ss], deviceSuffix[ds], formatSuffix[fs]];
                NSURL*      testURL = [rootURL URLByAppendingPathComponent:nameXX];
                NSLog(@"testing if image exists: %@", testURL);
                if([testURL checkResourceIsReachableAndReturnError:nil])
                {
                    imageURL = testURL;
                    imageScale = scaleValues[ss];
                    break;
                }
            }
        }
    }

    // If a suitable file was found...
    if(imageURL != nil)
    {
        // ...load and cache the image
        image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:imageURL]];
        image = [UIImage imageWithCGImage:image.CGImage scale:imageScale orientation:UIImageOrientationUp];
        NSLog(@"Image loaded, with scale: %f", image.scale);
        if(cache == nil)
        {
            cache = [NSCache new];
            objc_setAssociatedObject([UIApplication sharedApplication].delegate, @"imageCache", cache, OBJC_ASSOCIATION_RETAIN);
        }
        [cache setObject:image forKey:cacheKey];
    }
    return image;
}

問題があれば教えてください。私の知る限り、セマンティクスは次のようなものですimageNamed:-少なくとも最も一般的なケースでは。たぶん、さまざまな画像形式や私が知らない他のいくつかの修飾子がたくさんあります-それをサポートするためにコードを変更するのはかなり簡単なはずです。

于 2012-06-17T02:58:19.270 に答える
0

これでうまくいくと思います。画面のスケールを確認する簡単なテストです。

UIImage *image;
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2){
  // @2x
  NSURL *imageURL = [NSURL URLWithString:@"http://www.example.com/images/yourImage@2x.png"];
  NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
  image = [UIImage imageWithData:imageData];
} else {
  // @1x
  NSURL *imageURL = [NSURL URLWithString:@"http://www.example.com/images/yourImage.png"];
  NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
  image = [UIImage imageWithData:imageData];
}
UIImageView *yourImageView = [[UIImageView alloc] initWithImage:image];

ここで回答 済みですURLからロードする場合、網膜/通常の画像はどのように処理する必要がありますか?

それが役に立てば幸い

于 2012-06-17T01:32:31.790 に答える