これは私が思いついた最高のものです。フレームワークで動作を複製するため(おそらく微妙な不整合があるため)理想的ではありませんが、私たちが望む素晴らしいことを実行し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:
-少なくとも最も一般的なケースでは。たぶん、さまざまな画像形式や私が知らない他のいくつかの修飾子がたくさんあります-それをサポートするためにコードを変更するのはかなり簡単なはずです。