参考链接:http://blog.youkuaiyun.com/ys410900345/article/details/26503279
在修改xcode比较大的项目时,通常会遇到一种很蛋疼的情况: 项目中很多地方调用一个方法,但是这个方法的功能不太理想,于是你想修改这个方法,最后发现这个方法来源于一个Lib, 没有代码,只有 定义在 .h 文件,泥马没有代码怎么修改阿?
小牛哥在做 Westfield Leasing 这个项目时也遇到类似的操蛋经历,这个app用到很多tmd大图片,一般正常人都用 [UIImage imageNamed: ] 这个方法,但是在调试中发现,泥马这个方法会不断占用cash的内存,导致程序很快就阳痿(内存不够)! 而 [UIImage imageWithContentsOfFile:] 就不会。
这样我们单独写一个方法好了, 像[UIImage xpImageNamed:] 这样的category! 里面调用imageWithContentsOfFile: 就好了?
听起来可行,但两个问题:
1. 在一个大项目里,人员流动也频繁,有新人进来你得不断的告诉他/她:别用imageNamed:啦,会阳痿的。。。 要是新人是个小清纯,你好意思不?
2. 项目里原来可能就有几百个地方用imageNamed:, 如果用一个新的函数代替,将会有几百个地方要修改,这个不是高效率的方法。 而且当你commit 代码时,别的程序员看到这么多地方被修改,得拿出看AV的认真态度,多累阿。。。
**
所以最好的方法是在整个项目中替换掉imageNamed:这个方法, 当其他人用这个方法时,系统其实会调用另一个方法!
请看下面代码!
以下方法称为 Method Swizzling, 当你引用下面的头文件时,在整个项目中[UIImage imageNamed: ] 这个方法会被 [UIImage myImageNamed:] 这个方法替换掉。
PS:
在iOS7中, 如果你的 UIBarButtonItem 是以 initWithCumstomView: 建立的,会出现移位的情况,这时可以用 Method Swizzling 来解决,详情请关注小牛的的下一篇文章。
#import <UIKit/UIKit.h>
@interface UIImage (Common)
+(UIImage*)myImageNamed: (NSString*)imageName;
@end
#import "UIImage+Common.h"
#import <objc/runtime.h>
#import <objc/message.h>
@implementation UIImage (Common)
// load 在初始化类时调用,每个类都有一个load 方法,
// 类的初始化先于对象
+(void)load
{
//以下方法就告诉系统用后面的方法替换前面的
method_exchangeImplementations(class_getClassMethod(self, @selector(imageNamed:)),
class_getClassMethod(self, @selector(myImageNamed:)));
}
+(UIImage*)myImageNamed: (NSString*)imageName
{
// 图片要支持jpg 和png
NSString *path = [[NSBundle mainBundle] pathForResource:imageName ofType:@"png"];
if (path == nil)
{
path = [[NSBundle mainBundle] pathForResource:imageName ofType:@"jpg"];
}
// 这里image 在回收后不会占用cash 内存
UIImage *image = [UIImage imageWithContentsOfFile:path];
return image;
}
@end