iOS 封装runtime库,一句话可实现方法交换

作者 : 开心源码 本文共2366个字,预计阅读时间需要6分钟 发布时间: 2022-05-13 共265人阅读

长话短说,直接上代码比较直观:

[CCRuntime exchangeMethod:[self class] name:@"viewWillAppear:" withBlock:^void(id _self, BOOL animated) {    NSLog(@"已经被hook了");        // 原来的方法实现会被交换至新的方法,方法名可通过下面获取      // 回调原来viewWillAppear里面的代码    [_self performSelector:NSSelectorFromString([CCRuntime exchangeOriginMethodUsingSelectorName:@"viewWillAppear:"]) withObject:@(animated)];}];

至此,viewWillAppear已经成功被替换掉了。在回调viewWillAppear之前,会先执行打印代码。

如何实现?

我把原方法的实现替换成block,原方法的实现丢到一个新的方法。新的方法名可获取,有需要再回调就可。点击下载源码

其它详情

除了方法交换之处,我还提供了其它API,提供更为便携地通过runtime操作方法、类、属性:

方法

一、为类动态增加一个方法,用block去构造方法实现:

[CCRuntime addMethodTo:[self class] name:@"getUserName:" withBlock:^int(id _self, int *userId){    NSLog(@"userId是:%d", userId);    return @"Allan";} returnType:@"id" paramTypes:@[@"int"]];

二、为类动态增加一个方法,用已有方法去构造方法实现:

[CCRuntime addMethodTo:[self class] name:@"bar" from:[self class] name:@"foo"];[self performSelector:NSSelectorFromString(@"bar")]; /* 打印:我是foo */-(void)foo {    NSLog(@"我是foo");}

三、重置一个方法的实现,用block重置

[CCRuntime resetMethod:[self class] name:@"foo" withBlock:^{    NSLog(@"我不是foo了呀");}];[self foo]; /* 打印:我不是foo了呀 */

四、交换一个方法,这个方法会以block作为方法实现:

[CCRuntime exchangeMethod:[self class] name:@"viewWillAppear:" withBlock:^void(id _self, BOOL animated) {    NSLog(@"已经被hook了");        // 原来的方法实现会被交换至新的方法,方法名可通过下面获取      // 回调原来viewWillAppear里面的代码    [_self performSelector:NSSelectorFromString([CCRuntime exchangeOriginMethodUsingSelectorName:@"viewWillAppear:"]) withObject:@(animated)];}];

在之前,我们进行方法交换的一般做法是:多写一个方法,而后在初始化时用runtime库交换实现。

现在可以优雅地聚合代码和快速实现需求了。

属性

获取属性列表:

NSArray *props = [CCRuntime getPropertyListOnlyName:[self class]];

为对象属性增加动态属性:

UIViewController *vc = [UIViewController new];/* 相似分类增加属性的做法,好处是不必再多写一个分类文件 */[CCRuntime setObject:vc copyValue:@"广州" forKey:@"address"];NSLog(@"address是:%@", [CCRuntime object:vc valueForKey:@"address"]);

动态创立一个类:

Class cls = [CCRuntime buildClass:[UIViewController class] name:@"TestViewController" ivarAndMethodBulider:^(Class  _Nonnull __unsafe_unretained cls) {    // 可在block里面增加成员变量&方法    [CCRuntime addIvar:cls name:@"name"];    [CCRuntime addMethodTo:cls name:@"test" withBlock:^{        NSLog(@"i am test控制器的方法");    } returnType:@"void" paramTypes:@[]];}];UIViewController *vc = (UIViewController *)[CCRuntime getClassInstance:cls];// 1.测试下成员变量[CCRuntime setIvarValue:vc name:@"name" value:@"i am test控制器"];NSLog(@"%@", [CCRuntime getIvarValue:vc name:@"name"]);// 2.测试下方法[vc performSelector:NSSelectorFromString(@"test")];// 3.尝试下present刚才动态创立的类vc.view.backgroundColor = [UIColor cyanColor];[self presentViewController:vc animated:YES completion:nil];
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » iOS 封装runtime库,一句话可实现方法交换

发表回复