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.

Show comment
Hide comment
@waynehartman

waynehartman 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];
}

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.

Show comment
Hide comment
@0xced

0xced 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 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.

Show comment
Hide comment
@0xced

0xced 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.

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.

Show comment
Hide comment
@steipete

steipete Sep 14, 2012

attribute((constructor)) is your friend :)

steipete commented Sep 14, 2012

attribute((constructor)) is your friend :)

@0xced

This comment has been minimized.

Show comment
Hide comment
@0xced

0xced Sep 14, 2012

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

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.

Show comment
Hide comment
@artemstepanenko

artemstepanenko 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 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.

Show comment
Hide comment
@artemstepanenko

artemstepanenko 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.

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.

Show comment
Hide comment
@rufferto

rufferto Sep 19, 2012

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

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.

Show comment
Hide comment
@artemstepanenko

artemstepanenko Sep 19, 2012

I think it's a good idea

artemstepanenko commented Sep 19, 2012

I think it's a good idea

@angelolloqui

This comment has been minimized.

Show comment
Hide comment
@angelolloqui

angelolloqui 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

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.

Show comment
Hide comment
@plenilune

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.

Show comment
Hide comment
@furkanmustafa

furkanmustafa 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.

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.

Show comment
Hide comment
@pombredanne

pombredanne Mar 14, 2018

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

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