這是我想出來的最好的事情。這並不理想,因爲它在框架中重複行爲(可能有微妙的不一致性),但它會從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:
- 至少對於最常見的情況。也許有不同的圖像格式和其他修飾符的加載我不知道 - 代碼應該很容易修改以支持。
這可能有些用處:http://blog.mro.name/2010/11/high-res-uiimage-remote-load/ –
這不會做我想要的行爲 - 即檢查哪些文件存在如果它們不存在,則回落到其他的緩存中。無論如何,我最終寫了自己的一個(代碼張貼在答案中)。 – jhabbott