iOS中IMP指针的运用
2015-07-28 17:25
393 查看
iOS中IMP指针的运用
Runtime中的IMP指针
ios中如果对Runtime有一定了解的话,一定听说过或者用过这个函数void method_exchangeImplementations(Method m1, Method m2),它通常就是所说的method swizzling,算是ObjC的”黑魔法”了,作用就是在程序运行期间动态的给两个方法互换实现;
比如:
程序中有许多个ViewController,我想在对项目改动最小的情况下,在当每个Controller执行完ViewDidLoad以后就在控制台把自己的名字打印出来,方便去做调试或者了解项目结构
其实我们的目的就是重写ViewDidLoad的方法,并在他的方法最后加上几句Log,所以我们需要给UIViewController建立一个category,因为我们知道,如果在Catagory中重写一个方法,就会覆盖它的原有方法实现,但是,这样做以后就没有办法调用系统原有的方法,因为在一个方法里调用自己的方法会是一个死循环。所以我们的解决办法就是,另外写一个方法来和viewDidLoad“交换”,这样外部调用viewDidLoad就会调到新建的这个方法中,同样,我们调用新建的方法就会调用到系统的viewDidLoad中了
第一种方案:
#import "UIViewController+viewDidLoad.h" #import <objc/runtime.h> @implementation UIViewController (viewDidLoad) + (void)load { //保证交换方法只执行一次 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ //获取这个类的viewDidLoad方法,它的类型是一个objc_moethod结构体的指针 Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad)); //获取自定义的方法 Method viewDidLoaded = class_getInstanceMethod(self, @selector(viewDidUnload)); //互换两个方法实现 method_exchangeImplementations(viewDidLoad, viewDidLoaded); }); } //新建一个方法与viewDidload交换 - (void)viewDidLoaded { [self viewDidLoaded]; NSLog(@"%@ did load",self); }
第二种方案:
IMP 它是一个指向方法实现的指针,每一个方法都一个对应的IMP指针。我们可以直接调用方法的IMP指针,来避免方法调用死循环的问题
//修改的方法有返回值就用IMP,无返回值就用VIMP typedef id (*_IMP) (id,SEL,...); typedef void (*_VIMP) (id,SEL,...); #import "UIViewController+viewDidLoad.h" #import <objc/runtime.h> @implementation UIViewController (viewDidLoad) + (void)load { //保证交换方法只执行一次 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ //获取原始方法 Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad)); //获取方法实现 _VIMP viewDidLoad_IMP = (_VIMP)method_getImplementation(viewDidLoad); //重新设置方法实现 method_setImplementation(viewDidLoad,imp_implementationWithBlock(^(id target,SEL action){ viewDidLoad_IMP(target,@selector(viewDidLoad)); //自定义代码 NSLog(@"%@ did load",target); })); }); }
需要注意事项
修改的方法有返回值就用IMP,没有返回值就用VIMP。重写的方法有返回值,不要忘记在最后做return实际上直接调用一个方法的IMP指针的效率是高于调用方法本身的,如果有一个合适的时机获取到方法的IMP的话,可以试着调用IMP而不用调用方法。
相关文章推荐
- IOS- 得到系统版本
- iOS多态
- iOS开发使用nib进行界面设计并跳转
- iOS—修改AFNetworking源文件可接收text/plain的方法
- IOS-写文件到本地
- [iOS]NSString到底使用Copy还是使用Strong属性,有什么区别
- iOS 中如何预览HTML中的图片
- iOS中的KVC
- Gios WORD .NET Library (using RTF specification)
- [Link]用HTML5/CSS3/JS开发Android/IOS应用
- iOS开发问题之:应用语言是英文
- 程序日志--ios“点数器”程序
- iOS检测耳机是否插入
- iOS通知问题之:一眼就看懂的NSNotificationCenter应用
- iOS 检测设备旋转状态
- iOS支付宝问题之:调用支付宝AlipaySDK找不到头文件<openssl/rsa.h>
- iOS每日一记之——————炒鸡好用的27个第三方库!!!
- 27个提升效率的iOS开源库推荐
- [iOS]cell重用机制会重叠显示
- iOS-按钮的代码封装