Runtime使用

获取isa指向的Class,如果person是实例对象,获取得是类对象。如果person是类对象,获取得是元类对象
object_getClass(person)
获取父类
class_getSuperclass([person class])

//设置isa指向的Class

 #import 
#import 
#import "Person.h"
#import "Cat.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc]init];
        [person run];
        object_setClass(person,[Cat class]);
        [person run];
    }
    return 0;
}

//运行结果为:
2021-09-29 11:29:14.438525+0800 Test[47604:2583284]  -[Person run]
2021-09-29 11:29:14.439851+0800 Test[47604:2583284]  -[Cat run]

iOS的KVO实现就使用到这个API,系统会将isa指针设置为被观察的衍生子类。

判断一个OC对象是否为Class
object_isClass(person)
判断一个class对象是否为元类
class_isMetaClass([person class]);

动态创建类、成员变量、方法

#import 
#import 
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //创建类
        Class newClass = objc_allocateClassPair([NSObject class], "Gog", 0);
        //添加成员变量,不能放到注册类的后面,成员变量存储在 class_ro_t只读的数据结构
        // 8 : 代表成员变量占用内存大小    1 : 对齐方式,此处固定写1
        class_addIvar(newClass, "_name", 8, 1, "@");
        //添加方法。可以放在注册类后,方法放在class_rw_t中,是可读可写得数据结构
        class_addMethod(newClass, @selector(run), (IMP)run, "v@:");
        //注册类
        objc_registerClassPair(newClass);
        id dog = [[newClass alloc] init];
        //成员变量没有set,get方法,不能使用点语法,只能使用Kvc进行赋值取值
        [dog setValue:@"abc" forKey:@"_name"];
        NSLog(@"%@",[dog valueForKey:@"_name"]);
        [dog run];
        
    }
    return 0;
}

//运行结果为:
2021-09-29 15:58:49.216396+0800 Interview01-cache[48615:2661474] abc
2021-09-29 15:58:49.217449+0800 Interview01-cache[48615:2661474]   run

获取成员变量信息及赋值与取值

#import 
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
    Person *person = [[Person alloc]init];
         //获取成员变量信息
       Ivar ageIvar = class_getInstanceVariable([Person class], "_age");
        Ivar nameIvar = class_getInstanceVariable([Person class], "_name");
        NSLog(@"%s   %s",ivar_getName(ageIvar),ivar_getName(nameIvar));
        //设置和获取成员变量的值
        object_setIvar(person, ageIvar, @10); //方法第三个参数必须传OC对象类型的值,如果传入基本类型的值会报错  No matching function for call to 'object_setIvar'   
         object_setIvar(person, ageIvar,  (__bridge id)(void *)10) ; //经过这样转换就可以成功
        object_setIvar(person, nameIvar, @"abc");
        NSLog(@"%d   %@",person.age,person.name);
        
    }
    return 0;
}

//运行结果为:
2021-09-29 16:51:37.145394+0800 Interview01-cache[48878:2680369] _age   _name
2021-09-29 16:51:37.146843+0800 Interview01-cache[48878:2680369] -753417967   abc

从上面代码运行结果我们发现_age的值没有设置成功,因为我们在设置值时将它包装成了NSNumber类型,再赋值给int是会失败,object_setIvar 方法有不允许我们直接传int类型的值,所以我们想给基础类型的成员变量赋值是可以使用kvc

成员变量的数量

  unsigned int count;
  Ivar *ivars = class_copyIvarList([MJPerson class], &count); //返回的是数组,指针可以当做数组使用
  for (int i = 0; i < count; i++) {
        //取出i位置的成员变量
         Ivar ivar = ivars[i];
         NSLog(@"%s  ",ivar_getName(ivar));
     }
    free(ivars);

什么是Runtime?平时项目中有用过么?
OC是一门动态性比较强的编程语言,允许很多操作推迟到程序运行时再进行
OC的动态性就是有Runtime来支撑和实现的,Runtime是一套C语言的API,封装了很多动态性相关的函数
平时编写的OC代码,底层都是转换成了RuntimeAPI进行调用的
利用关联对象给分类添加属性
遍历类的所有成员变量(修改私有变量,字典转模型,归档解档)
交换方法实现(交换系统的方法)
利用消息转发机制解决方法找不到的问题

你可能感兴趣的:(Runtime使用)