Runtime 交换方法

作者: 留个念想给昨天 | 来源:发表于2018-04-03 17:01 被阅读21次

他喜欢创作,时常有充沛的表达诉求,
他喜欢听王菲的歌,也向往远方和自由。
他希望有人懂他偶尔的烦躁和头脑短路,
懂他有时写文案也是带着镣铐在跳舞。
然而,他洞察过那么多消费者的心,
却没有人还给他一个“懂得”。

于是他,转行了,做了iOS开发人!

写在前头

工作中,是不是经常这样用到NSURL
NSURL * url = [NSURL URLWithString:@"www.baidu.com"];
很简单,但是!!! 有个致命的隐藏问题 !!!!
当字符串中有中文,这个url就创建不成功,那么我们发送的请求就会出错。
是不是有这样的经历:发现一个问题,找bug找了半天,最后发现是url中有中文。。。(此处是不是想摔电脑)
那么有什么办法在不改变原有代码的情况下给URLWithString 添加一个检测是否为空的功能?

这里就要用到runtime的方法交互了。

image.png

1.创建NSURL的分类

#import <Foundation/Foundation.h>

@interface NSURL (url)

+(instancetype)My_URLWithString:(NSString *)URLString;

@end

#import "NSURL+url.h"
@implementation NSURL (url)

+(instancetype)My_URLWithString:(NSString *)URLString
{
    NSURL * url = [NSURL URLWithString:URLString];
    if (url == nil) {
        NSLog(@"哥么是一个空的URL");
    }
    return url;
    
}

@end

这个My_URLWithString 就是检测url为空的方法
那么应该怎么交换方法呢,什么时候交换呢

2.寻找方法交换的时机

每一个类,只要参与了编译,就会加载这个类,只要加载这个类就会调用这个类的load方法。
试一下

#import "NSURL+url.h"

@implementation NSURL (url)

+(void)load
{
    NSLog(@"%s",__func__);
    
}


+(instancetype) My_URLWithString:(NSString *)URLString
{
    NSURL * url = [NSURL URLWithString:URLString];
    if (url == nil) {
        NSLog(@"哥么这个URL为空");
    }
    return url;
    
}
@end

然后在ViewController中调用URLWithString:这个方法

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSURL * url = [NSURL URLWithString:@"www.baidu.com/中文"];
}
@end

运行,会发现,没有引用NSURL+url 这个类,也没有调用My_URLWithString这个方法,这个load也走了。

image.png

那么,我们可以在load中添加方法交互

3.方法交换

#import "NSURL+url.h"
#import <objc/message.h>

@implementation NSURL (url)

+(void)load
{
    //获取类方法
    //1.类类型
    //2.方法编号
    Method URLWithStr = class_getClassMethod([NSURL class], @selector(URLWithString:));
    //My_URLWithString
    Method MyURLWithStr = class_getClassMethod([NSURL class], @selector(My_URLWithString:));
    //交换方法
    method_exchangeImplementations(URLWithStr, MyURLWithStr); 
    
}
+(instancetype)My_URLWithString:(NSString *)URLString
{
    NSURL * url = [NSURL URLWithString:URLString];
    if (url == nil) {
        NSLog(@"哥么这个URL为空");
    }
    return url;
}
@end

辛辛苦苦,来一发测试
打个断点,看有没有走My_URLWithString:方法

image.png

果断进来了,放开断点

image.png

百密一疏

+(instancetype)My_URLWithString:(NSString *)URLString
{
    //注意这里----一定一定要标注好
    NSURL * url = [NSURL My_URLWithString:URLString];
    if (url == nil) {
        NSLog(@"哥么这个URL为空");
    }
    return url;
    
}

这样就OK了。完美解决,没有改变原有的任何代码。
提供一份Demo,希望对你有帮助
想了解更多RunTime,可以参考:
Runtime 消息传递机制
Runtime 消息转发机制
写在最后:

希望这篇文章对您有帮助,最好就是实操一边,这样才能理解更深入。
当然如果您发现有可以优化的地方,希望您能慷慨的提出来。
最后祝您工作愉快!

相关文章

  • runtime

    runtime交换方法 动态添加方法

  • runTime常用方法

    使用runTime改变实例成员的值 使用runtime来交换两个方法 注意再次调用该方法不交换 使用runTime...

  • Runtime

    runtime运行时机制1:通过runtime,实现方法交换(交换两个类方法、交换两个实例方法)2:通过runti...

  • Day3

    1 runtime运行时机制1:通过runtime,实现方法交换(交换两个类方法、交换两个实例方法)。2:通过ru...

  • runtime的理解(二)

    主要内容 利用 runtime 交换方法 利用 runtime 动态添加方法 利用 runtime 动态添加属性 ...

  • 查看SDK调用支付宝参数

    使用runtime 方法交换openurl

  • objc runtime (四)动态添加属性

    在《objc runtime (二)交换方法》中我提到过runtime最实用的就是交换方法和动态添加属性两个用法。...

  • iOS runtime如何交换两个类方法

    如有转载,请标明出处:iOS runtime如何交换两个类方法 runtime交换实例方法,老生常谈的问题,很多b...

  • iOS -- runtime的应用

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

  • runtime和oc内存区域(2018-04-02)

    runtime常用的几个方法: 交换方法 动态添加属性 动态添加方法 1.交换方法 class_getClassM...

网友评论

本文标题:Runtime 交换方法

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