美文网首页
Runtime-Swizzling方法交换

Runtime-Swizzling方法交换

作者: woniu | 来源:发表于2018-01-25 18:27 被阅读41次

公司项目开发要用到runtime来hook相应的方法啦,我会在接下来的时间逐渐实践并完善runtime的相关知识,然后分享给大家,也希望大家能指出我的错误。今天先开个坑(頑張れ)
今天就从runtime swizzling开始吧,swizzling方法的主要目的就是hook方法,实现方法的交换,下面的场景为我们交换页面的进入(viewWillAppear)和离开方法(viewWillDisappear)。


swizzling流程图.png

一、首先,我们要创建UIViewController的类别并导入:

#import "UIViewController+Swizzling.h"
#import <objc/runtime.h>//导入运行时库

二、在+load方法中调用相应的方法:

//Swizzling应该在+load方法中实现,因为+load方法可以保证在类最开始加载时会调用。runtime影响范围是全局的,以+load能够保证在类初始化的时候一定会被加载,这可以保证统一性。
+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //因为swizzling会改变全局,我们需要在运行时采取相应的防范措施。保证原子操作就是一个措施,确保代码即使在多线程环境下也只会被执行一次。
        [self methodSwizzlingWithOriginalSelector:@selector(viewWillAppear:) bySwizzledSelector:@selector(swizzledViewWillAppear:)];
        
        [self methodSwizzlingWithOriginalSelector:@selector(viewWillDisappear:) bySwizzledSelector:@selector(swizzledViewWillDisappear:)];
    });
}

三、进行方法的交换处理

*
 originalSelector:源方法
 swizzledSelector:我们要交换的方法
 */
+ (void)methodSwizzlingWithOriginalSelector:(SEL)originalSelector bySwizzledSelector:(SEL)swizzledSelector{
    Class class = [self class];
    //1、得到类的方法
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    //得到新的类的方法
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    //2、先尝试給源SEL添加IMP,这里是为了避免源SEL没有实现IMP的情况,一般源SEL都是实现的,所以返回NO
    BOOL didAddMethod = class_addMethod(class,originalSelector,
                                        method_getImplementation(swizzledMethod),
                                        method_getTypeEncoding(swizzledMethod));
    NSLog(@"-----------didAddMethod:%@",didAddMethod?@"YES":@"NO");
    /*
     由于源SEL一般都是实现的,万一没有实现,用我们添加的方法替换源SEL。所以,一般直接执行4.
     */
    
    if (didAddMethod) {
        //3、添加成功:说明源SEL没有实现IMP,将源SEL的IMP替换到交换SEL的IMP
        class_replaceMethod(class,swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        //4、添加失败:说明源SEL已经有IMP,直接将两个SEL的IMP交换即可
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

四、在交换方法中实现相应的功能

#pragma mnark 这里是hook的方法,在此处执行。
- (void)swizzledViewWillAppear:(BOOL)animated{
    [self swizzledViewWillAppear:animated];
    //在此处获取当前类的类名
    NSLog(@"进入页面获取当前类名:%@",NSStringFromClass([self class]));
}

- (void)swizzledViewWillDisappear:(BOOL)animated{
    [self swizzledViewWillDisappear:animated];
    NSLog(@"离开页面获取当前类名:%@",NSStringFromClass([self class]));
}

相关文章

  • Runtime-Swizzling方法交换

    公司项目开发要用到runtime来hook相应的方法啦,我会在接下来的时间逐渐实践并完善runtime的相关知识,...

  • iOS 方法交换

    交换类方法 交换实例方法

  • iOS -- runtime的应用

    runtime主要有一下几种应用场景 方法交换 添加属性 (一)方法交换 (1)字体适配 方法交换实际交换的是方法...

  • iOS 方法交换 method_exchangeImplemen

    方法交换 使用方法交换需要注意些什么呢 1、在交换系统方法后要注意结束前调用本方法,也就是执行系统方法 2、再交换...

  • OC runtime 底层API解析

    关于class的API 交换方法API 替换方法的实现 交换方法的实现

  • 交换方法

    利用runtime可以修改系统的方法实现,这种方式无任何侵入性,因此也是很多第三方常用的技术。它的解决具有全局性;...

  • 方法交换

    +(void)load load当类加载进内存的时候调用,而且不管有没有子类,都只会调用一次。在main函数之前调...

  • 交换方法

  • 交换方法

    几个函数 一、选择合适的时机,交换方法 二、替换方法内部使用注意

  • 交换方法

    // //ViewController.m //CocoTest_1 // //Created by S u p ...

网友评论

      本文标题:Runtime-Swizzling方法交换

      本文链接:https://www.haomeiwen.com/subject/hofbaxtx.html