Objectiv-C 方法调用偷龙转凤

来源:互联网 发布:工控机编程软件 编辑:程序博客网 时间:2024/06/03 07:58

在修改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:] 这个方法替换掉。

**

在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

0 0
原创粉丝点击