Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Swizzled UIImage imageNamed for iPhone 5
//
// UIImage+Retina4.h
// StunOMatic
//
// Created by Benjamin Stahlhood on 9/12/12.
// Copyright (c) 2012 DS Media Labs. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIImage (Retina4)
@end
//
// UIImage+Retina4.m
// StunOMatic
//
// Created by Benjamin Stahlhood on 9/12/12.
// Copyright (c) 2012 DS Media Labs. All rights reserved.
//
#import "UIImage+Retina4.h"
#import <objc/objc-runtime.h>
static Method origImageNamedMethod = nil;
@implementation UIImage (Retina4)
+ (void)initialize {
origImageNamedMethod = class_getClassMethod(self, @selector(imageNamed:));
method_exchangeImplementations(origImageNamedMethod,
class_getClassMethod(self, @selector(retina4ImageNamed:)));
}
+ (UIImage *)retina4ImageNamed:(NSString *)imageName {
NSLog(@"Loading image named => %@", imageName);
NSMutableString *imageNameMutable = [imageName mutableCopy];
NSRange retinaAtSymbol = [imageName rangeOfString:@"@"];
if (retinaAtSymbol.location != NSNotFound) {
[imageNameMutable insertString:@"-568h" atIndex:retinaAtSymbol.location];
} else {
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
if ([UIScreen mainScreen].scale == 2.f && screenHeight == 568.0f) {
NSRange dot = [imageName rangeOfString:@"."];
if (dot.location != NSNotFound) {
[imageNameMutable insertString:@"-568h@2x" atIndex:dot.location];
} else {
[imageNameMutable appendString:@"-568h@2x"];
}
}
}
NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageNameMutable ofType:@"png"];
if (imagePath) {
return [UIImage retina4ImageNamed:imageNameMutable];
} else {
return [UIImage retina4ImageNamed:imageName];
}
return nil;
}
@end
//
// UIImage+Retina4.h
// StunOMatic
//
// Created by Benjamin Stahlhood on 9/12/12.
// Copyright (c) 2012 DS Media Labs. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIImage (Retina4)
@end
//
// UIImage+Retina4.m
// StunOMatic
//
// Created by Benjamin Stahlhood on 9/12/12.
// Copyright (c) 2012 DS Media Labs. All rights reserved.
//
#import "UIImage+Retina4.h"
#import <objc/runtime.h>
#import <objc/message.h>
static Method origImageNamedMethod = nil;
@implementation UIImage (Retina4)
+ (void)initialize {
origImageNamedMethod = class_getClassMethod(self, @selector(imageNamed:));
method_exchangeImplementations(origImageNamedMethod,
class_getClassMethod(self, @selector(retina4ImageNamed:)));
}
+ (UIImage *)retina4ImageNamed:(NSString *)imageName {
NSLog(@"Loading image named => %@", imageName);
NSMutableString *imageNameMutable = [imageName mutableCopy];
NSRange retinaAtSymbol = [imageName rangeOfString:@"@"];
if (retinaAtSymbol.location != NSNotFound) {
[imageNameMutable insertString:@"-568h" atIndex:retinaAtSymbol.location];
} else {
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
if ([UIScreen mainScreen].scale == 2.f && screenHeight == 568.0f) {
NSRange dot = [imageName rangeOfString:@"."];
if (dot.location != NSNotFound) {
[imageNameMutable insertString:@"-568h@2x" atIndex:dot.location];
} else {
[imageNameMutable appendString:@"-568h@2x"];
}
}
}
NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageNameMutable ofType:@"png"];
if (imagePath) {
return [UIImage retina4ImageNamed:imageNameMutable];
} else {
return [UIImage retina4ImageNamed:imageName];
}
return nil;
}
@end
@waynehartman

This comment has been minimized.

Copy link

waynehartman commented Sep 13, 2012

How is this working out for you? For me it is loading the image thinking that it has a scale of 1.0. I found that I needed to create the image, setting its scale to properly work:

if (imagePath) {
UIImage* image = [UIImage retina4ImageNamed:imageNameMutable];
if (isIPhone5) {
image = [UIImage imageWithCGImage:image.CGImage scale:2.0f orientation:UIImageOrientationUp];
}

    return image;
} else {
    return [UIImage retina4ImageNamed:imageName];
}
@0xced

This comment has been minimized.

Copy link

0xced commented Sep 14, 2012

By overriding the +initialize method in the Retina4 category, you just nuked the cache flushing mechanism since it’s setup in +[UIImage initialize].

@0xced

This comment has been minimized.

Copy link

0xced commented Sep 14, 2012

You should put the swizzle code in the +load method instead of the +initialize method. Also, this gist has UIImage+Retina4.h and UIImage+Retina4.m two times.

@steipete

This comment has been minimized.

Copy link

steipete commented Sep 14, 2012

attribute((constructor)) is your friend :)

@0xced

This comment has been minimized.

Copy link

0xced commented Sep 14, 2012

I prefer +load over __attribute__((constructor)) but that’s really a matter of taste.

@artemstepanenko

This comment has been minimized.

Copy link

artemstepanenko commented Sep 18, 2012

And what about this image name: @"MyBundle.bundle/picture.png"? In this case your code will try to insert @"-568h@2x" before the wrong dot.

@artemstepanenko

This comment has been minimized.

Copy link

artemstepanenko commented Sep 18, 2012

This category won't work for image names which include extension.
You have to delete extension from imageNameMutable before 40'th line.

@rufferto

This comment has been minimized.

Copy link

rufferto commented Sep 19, 2012

How about not even swizzling this unless you know you are running on a retina4 device?

@artemstepanenko

This comment has been minimized.

Copy link

artemstepanenko commented Sep 19, 2012

I think it's a good idea

@angelolloqui

This comment has been minimized.

Copy link

angelolloqui commented Sep 28, 2012

I rewrote the code to fix some of the commented issues. Check it out at: http://angelolloqui.com/blog/20-iPhone5-image-loading

@plenilune

This comment has been minimized.

Copy link

plenilune commented Oct 1, 2012

Apple rejects apps that use method swizzling http://stackoverflow.com/questions/7720947/method-swizzling-in-ios-5

@furkanmustafa

This comment has been minimized.

Copy link

furkanmustafa commented Sep 6, 2013

Apple doesn't reject apps that use method swizzling. The rejected app in the provided link swizzles 'dealloc' method, and that's clearly mentioned in Apple's email there.

For this case it should be completely OK. I already have several apps in the store using method swizzling.

@pombredanne

This comment has been minimized.

Copy link

pombredanne commented Mar 14, 2018

@bstahlhood thanks for this... what would be the license for these snippets?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.