美文网首页
第13条:用“方法调配技术”调试“黑盒方法”

第13条:用“方法调配技术”调试“黑盒方法”

作者: MrSYLong | 来源:发表于2018-08-18 23:26 被阅读8次

    第11条说过:OC对象收到消息后,调用何种方法需要在运行期才能解析出来,所以给定的选择器名称相对应的方法,可以在运行期改变。不需要源代码和继承子类来覆写。新功能将在本类所有的实例中生效,这个方法叫“方法调配”(method swizzling)。

    类的方法列表会把选择器的名称映射到相关方法的实现之上,使“动态消息派发系统”能够根据选择器的名称找到应该调用的方法。方法均以函数指针的形式来表示,这种指针叫做IMP。

    id (*IMP)(id, SEL, ...)
    

    开发者可以向类的选择器映射表中新增方法,也可以改变选择器所对应的方法实现,还可以交换两个选择器所映射的指针。


    NSString类的选择器映射表.jpg NSString类修改后的选择器映射表.jpg

    交换方法实现:

    void method_exchangeImplementations(Method m1, Method m2)
    
    参数:表示待交换的两个方法实现 
    

    获取方法实现:

    Method class_getInstanceMethod(Class cls, SEL name)
    
    参数:类,相关方法
    

    互换两个已经写好的方法实现:

    // 示例:
    Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
    Method swappedMethod = class_getInstanceMethod([NSString class], @selector(uppercaseString));
    
    method_exchangeImplementations(originalMethod, swappedMethod);
    
    NSString *string = @"This is the Stirng";
    NSString *lowercaseString = [string lowercaseString];
    NSLog(@"lowercaseString: %@",lowercaseString);
    
    NSString *uppercaseString = [string uppercaseString];
    NSLog(@"uppercaseString: %@",uppercaseString);
    
    输出:
    2018-08-18 23:11:38.549956+0800 Demo[12577:491276] lowercaseString: THIS IS THE STIRNG
    2018-08-18 23:11:38.550262+0800 Demo[12577:491276] uppercaseString: this is the stirng
    
    说明:
    交换NSString类的lowercaseString与uppercaseString实现。
    

    为既有方法实现新增新功能:

    // 新建NSString类分类,头文件
    #import <Foundation/Foundation.h>
    
    @interface NSString (EOCMyAdditions)
    
    - (NSString *)eoc_myLowercaseString;
    
    @end
    
    // 实现文件
    #import "NSString+EOCMyAdditions.h"
    
    @implementation NSString (EOCMyAdditions)
    
    - (NSString *)eoc_myLowercaseString
    {
        NSString *lowercase = [self eoc_myLowercaseString];
        NSLog(@"%@ => %@",self, lowercase);
        return lowercase;
    }
    
    @end
    
    // 使用
    Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
    Method swappedMethod = class_getInstanceMethod([NSString class], @selector(eoc_myLowercaseString));
    
    method_exchangeImplementations(originalMethod, swappedMethod);
    
    NSString *string = @"This is the Stirng";
    NSString *lowercaseString = [string lowercaseString];
    
    输出:
    2018-08-18 23:17:24.038765+0800 Demo[12721:496759] This is the Stirng => this is the stirng
    

    这样可以为“完全不知道具体实现”的黑盒方法增加日志记录功能。
    一般,只有在调试程序的时候才需要在运行期修改方法实现,不宜滥用。

    相关文章

      网友评论

          本文标题:第13条:用“方法调配技术”调试“黑盒方法”

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