Skip to content

Instantly share code, notes, and snippets.

@angelolloqui
Last active October 6, 2022 16:35
Show Gist options
  • Star 42 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save angelolloqui/3799648 to your computer and use it in GitHub Desktop.
Save angelolloqui/3799648 to your computer and use it in GitHub Desktop.
iPhone5 UIImage method swizzling to load -568h images
//
// UIImage+H568.m
//
// Created by Angel Garcia on 9/28/12.
// Copyright (c) 2012 angelolloqui.com. All rights reserved.
//
#import <objc/runtime.h>
@implementation UIImage (H568)
+ (void)load {
if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) &&
([UIScreen mainScreen].bounds.size.height > 480.0f)) {
//Exchange XIB loading implementation
Method m1 = class_getInstanceMethod(NSClassFromString(@"UIImageNibPlaceholder"), @selector(initWithCoder:));
Method m2 = class_getInstanceMethod(self, @selector(initWithCoderH568:));
method_exchangeImplementations(m1, m2);
//Exchange imageNamed: implementation
method_exchangeImplementations(class_getClassMethod(self, @selector(imageNamed:)),
class_getClassMethod(self, @selector(imageNamedH568:)));
}
}
+ (UIImage *)imageNamedH568:(NSString *)imageName {
return [UIImage imageNamedH568:[self renameImageNameForH568:imageName]];
}
- (id)initWithCoderH568:(NSCoder *)aDecoder {
NSString *resourceName = [aDecoder decodeObjectForKey:@"UIResourceName"];
NSString *resourceH568 = [UIImage renameImageNameForH568:resourceName];
//If no 568h version, load as default
if ([resourceName isEqualToString:resourceH568]) {
return [self initWithCoderH568:aDecoder];
}
//If 568h exists, load with [UIImage imageNamed:]
else {
return [UIImage imageNamedH568:resourceH568];
}
}
+ (NSString *)renameImageNameForH568:(NSString *)imageName {
NSMutableString *imageNameMutable = [imageName mutableCopy];
//Delete png extension
NSRange extension = [imageName rangeOfString:@".png" options:NSBackwardsSearch | NSAnchoredSearch];
if (extension.location != NSNotFound) {
[imageNameMutable deleteCharactersInRange:extension];
}
//Look for @2x to introduce -568h string
NSRange retinaAtSymbol = [imageName rangeOfString:@"@2x"];
if (retinaAtSymbol.location != NSNotFound) {
[imageNameMutable insertString:@"-568h" atIndex:retinaAtSymbol.location];
} else {
[imageNameMutable appendString:@"-568h@2x"];
}
//Check if the image exists and load the new 568 if so or the original name if not
NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageNameMutable ofType:@"png"];
if (imagePath) {
//Remove the @2x to load with the correct scale 2.0
[imageNameMutable replaceOccurrencesOfString:@"@2x" withString:@"" options:NSBackwardsSearch range:NSMakeRange(0, [imageNameMutable length])];
return imageNameMutable;
} else {
return imageName;
}
}
@end
@angelolloqui
Copy link
Author

A quick explanation of the above code can be found at http://angelolloqui.com/blog/20-iPhone5-image-loading

@rt-Xor
Copy link

rt-Xor commented Dec 13, 2012

HI, Thanks for this little code it is so helpful for porting my app for iPhone5.
I have one query that , will apple approve this thing as we are making a category but we are also replacing their method of imageNamed with your Method . Basically we are overriding laod method of NSObject, i saw one post regarding category in which it was mentioned that we should avoid overriding method of NSObject while making any category. Please clear my doubts.

@skywalkerlw
Copy link

yes, my concern too. Apple could possible reject it.

@lochetti
Copy link

Did someone had a app rejected because of this change in the implementation?

Other question: Does this trick work with UIImages defined in the .xib file? (I did not call the "iimageNamed" method, in fact)

@angelolloqui
Copy link
Author

Answering your questions:

  1. Apple rejection: There is no reason for that. Method swizzling is allowed and used widely in many places, and imageNamed is a public method, so you are not going against any guideline. Besides, I have a few apps using this code without any problem.
  2. XIB files: UPDATE: The new version of the gist includes support for XIB files

I wrote some more info in http://angelolloqui.com/blog/20-iPhone5-568h-image-loading

@sundeepgupta
Copy link

Hi, 2 things I need to do to make this work flawlessly.

  1. Change the #import statement to: #import <objc/runtime.h>
  2. Wrap the load method code in an auto release pool.

@angelolloqui
Copy link
Author

I updated the Gist with changes to make XIB images also -568h compatible. Thanks to Alex Zak (@A-Zak) for pointing out a solution and specially to Artem Shimanski (@mrdepth) for inventing this trick for his own utility.

@aleksiy805
Copy link

It's all perfect, thank you very much

@shiweifu
Copy link

It's really helpful to me, thank you.

@ArtSabintsev
Copy link

I've been using this code (or similar code) for a good 18 months or so.

Quick suggestion - mind submitting this gist to CocoaPods? It'll need to be made into a full-fledged repo before you do so.

@normanhh3
Copy link

+1 for the CocoaPods suggestion!

@gongpengjun
Copy link

+1 for the CocoaPods suggestion!

@gongpengjun
Copy link

+1 for the CocoaPods suggestion!

@bohemima
Copy link

+1 for the CocoaPods suggestion!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment