iOS 使用runtime动态添加方法

使用runtime 动态添加方法的应用场景:

  • 如果一个类方法非常多,加载类到内存的时候也比较耗费资源,需要给每个方法生成映射表,可以使用动态给某个类,添加方法解决。

代码展示

#import "Person.h"
#import <objc/runtime.h>

@implementation Person

//调用了一个未实现方法时一定会执行 resolveInstanceMethod:方法
+(BOOL)resolveInstanceMethod:(SEL)sel {
    // 判断方法名是不是eat
    if (sel == NSSelectorFromString(@"eat")) {
        /**
         class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp,
                         const char * _Nullable types)
         1、Class  cls: 给哪个类添加方法
         2、SEL name:添加什么方法(方法的名称)
         3、IMP imp:一个新方法的实现函数,函数至少有两个参数id self和SEL _cmd
         4、const char * _Nullable types: 方法类型
                  v  没有返回值
                  @ 对象 id
                  :  方法
         5、返回值: 方法添加成功,则返回 YES,否则返回 NO(例如:该类已包含具有该名称的方法实现)。
         */
        //使用runtime 动态添加 eat 方法
        //添加了一个无返回值无参数的方法
        // v@: 表示一个void类型的方法,无返回值
        class_addMethod(self, @selector(eat), (IMP)eat, "v@:");
     } 
      
     if (sel == NSSelectorFromString(@"run:")) { 
        //添加无返回值有参数的方法
        // v@: 后面的 @ 表示一个对象类型的参数(例中NSNumber类型)
        class_addMethod(self, @selector(run:), (IMP)run, "v@:@");
     } 
      
     if (sel == NSSelectorFromString(@"play:")) {  
        //添加有返回值有参数的方法
        class_addMethod(self, @selector(play:), (IMP)play, "@@:@");
   } 
    
    return [super resolveInstanceMethod:sel];
}

// eat 方法实现
      // self:方法调用者
      // _cmd:当前方法编号
    // 任何一个方法都能调用self,_cmd,其实任何一个方法都有这两个隐式参数
void eat(id self, SEL _cmd) {
    NSLog(@"吃东西");
}

// run:方法的实现
void run(id self, SEL _cmd, NSNumber *meter) {
    NSLog(@"跑了 %@ 米", meter);
}

// play: 方法的实现
//返回值是一个 NSString 类型的数据
NSString *play(id self, SEL _cmd, NSString *ball) {
    NSLog(@"踢足球 - %@",ball);
    return ball;
}
@end
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {        
      //创建 Person 对象
        Person *p = [[Person alloc]init];
        //由于Person类中没有声明eat方法,无法直接用p对象调用,所以通过performSelector执行我们动态添加的eat方法。(调用没有实现的 eat 方法)
        [p performSelector:@selector(eat)];
        [p performSelector:@selector(run:) withObject:@"100"];
        NSString *ball = [p performSelector:@selector(play:) withObject:@"footerball"];
        NSLog(@"ball = %@", ball);
    }
    return 0;
}
打印的值
2022-08-03 12:18:37.195178+0800 Runtime 的相关应用场景[98335:2156011] 吃东西
2022-08-03 12:18:37.195801+0800 Runtime 的相关应用场景[98335:2156011] 跑了 1002022-08-03 12:18:37.195926+0800 Runtime 的相关应用场景[98335:2156011] 踢足球 - footerball
2022-08-03 12:18:37.195998+0800 Runtime 的相关应用场景[98335:2156011] ball = footerball
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
iOS Runtime是一种运行时环境,它是iOS操作系统中的重要组成部分。iOS Runtime为开发者提供了一套动态询问、修改和扩展应用程序行为的机制。 首先,iOS Runtime实现了Objective-C语言的动态特性。Objective-C是一种面向对象的编程语言,它具有动态特性,即在运行时能够动态地修改对象的行为。iOS Runtime允许开发者通过运行时系统对类、对象、方法以及属性进行动态操作。例如,开发者可以在运行时为某个类添加新的方法,也可以通过运行时修改类的实例变量。 其次,iOS Runtime还提供了消息发送机制。在Objective-C中,对象之间的通信是通过消息发送来完成的。iOS Runtime负责将消息转发给正确的接收者,并执行相应的方法。这个过程是动态的,开发者可以在运行时动态改变消息的接收者或方法的实现。这为Objective-C语言带来了很高的灵活性。 此外,iOS Runtime还支持方法的交换与替换。开发者可以通过运行时机制,在运行时将一个方法的实现替换为另一个方法的实现,或者交换两个方法的实现。这对于调试、性能监控和代码扩展都是非常有用的。 总结来说,iOS RuntimeiOS操作系统中实现Objective-C语言特性的核心组件。它提供了动态特性的支持,使开发者能够在运行时动态地修改类、对象和方法的行为,实现更加灵活和可扩展的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值