11.runtime 理解 和 常用点

问题

1.runtime 个人理解
2.runtime 常用api
3.runtime 日常运用解决问题
4.runtime 常用代码演练

答案

1.runtime 个人理解

1.OC是一门动态性比较强的编程语言,允许很多操作推迟到运行时在进行
2.OC的动态性就是有来支撑和实现的,runtime 是一套C语言的API,封装了很多动态性相关的api
3.平时编写的OC代码,底层都是转化成了 runtime api 进行调用

2.runtime 常用api

1.objc_xxx系列函数(关注于宏观使⽤,例如类与协议的空间分配、注册、注销等操作)

objc_getClass(const char * _Nonnull name) //获取Class对象
objc_getMetaClass //获取MetalClass对象
objc_allocateClassPair 分配空间,创建类(仅在创建之后,注册之前,能够添加成员变量)
objc_registerClassPair 注册⼀个类(注册后⽅可使⽤该类创建对象)
objc_disposeClassPair 注销某个类
objc_allocateProtocol 开辟空间创建协议
objc_registerProtocol 注册⼀个协议
objc_constructInstance 构造⼀个实例对象(ARC下⽆效)
objc_destructInstance 析构⼀个实例对象(ARC下⽆效)
objc_setAssociatedObject 为实例对象关联对象
objc_getAssociatedObject 获取实例对象的关联对象
objc_removeAssociatedObject 清空实例对象的所有关联对象
objc_msgSend 发送Objc消息

2.class_xxx系列函数(关注于类的内部,例如实例变量、属性、⽅法、协议等相关问题)

class_assIvar 为类添加实例变量
class_addProperty 为类添加属性
class_addMethod 为类添加⽅法
class_addProtocol 为类遵循协议
class_replaceMethod 替换类某⽅法的实现
class_getName 获取类名
class_isMetaClass 判断是否为元类
objc_getProtocol 获取某个协议
objc_copyProtocolList 拷⻉在运⾏时中注册过的协议列表
class_getSuperClass 获取某类的⽗类
class_setSuperClass 设置某类的⽗类
class_getProperty 获取某类的属性
class_getInstanceVariable 获取实例变量
class_getClassVariable 获取类变量
class_getInstanceMethod 获取实例⽅法
class_getClassMethod 获取类⽅法
class_getmethodImplementation 获取⽅法的实现
class_getInstanceSize 判断类是否实现某⽅法
class_respondsToSelector 判断类是否遵循某些以
class_createInstance 创建类的实例
class_copyIvarList 拷⻉类的实例变量列表
class_copyMethodList 拷⻉类的⽅法列表
class_copyProtocolList 拷⻉类遵循的协议列表
class_copyPropertyList 拷⻉类的属性列表

3.object_xxx系列函数(关注于对象的⻆度,例如实例变量)

object_copy 对象copy(ARC⽆效)
object_dispose 对象释放(ARC⽆效)
object_getClassName 获取对象的类名
object_getClass 获取对象的Class
object_setClass 设置对象的Class
object_getIvar 获取对象中实例变量的值
object_setIvar 设置对象中实例变量的值
object_getInstanceVariable 获取对象中实例变量的值(ARC中⽆效)
object_setInstanceVariable 设置对象中实例变量的值(ARC中⽆效)

4.method_xxx系列函数(关注于⽅法内部,例如⽅法的参数以及返回值类型和⽅法的实现)

method_getName 获取⽅法名
method_getImplementation 获取⽅法的实现
method_getTypeEncoding 获取⽅法的类型编码
method_getNumberOfArguments 获取⽅法的参数个数
method_copyReturnType 拷⻉⽅法的返回类型
method_getReturnType 获取⽅法的返回类型
method_copyArgumentType 拷⻉⽅法的参数类型
method_getArgumentType 获取⽅法的参数类型
method_getDescription 获取⽅法的描述
method_setImplementation 设置⽅法的实现
method_exchangeImplementations 替换⽅法的实现

5.property_xxx系列函数(关注于属性内部,例如属性的特性等)

property_getName 获取属性名
property_getAttributes 获取属性的特性列表
property_copyAttributeList 拷⻉属性的特性列表
property_copyAttributeValue 拷⻉属性中某特性的值

6.protocol_xxx系列函数(与协议相关)

protocol_conformsToProtocol 判断⼀个协议是否遵循另⼀个协议
protocol_isEqual 判断两个协议是否⼀致
protocol_getName 获取协议名称
protocol_copyPropertyList 拷⻉协议的属性列表
ptotocol_copyProtocolList 拷⻉某协议所遵循的协议列表
protocol_copyMethodDescriptionList 拷⻉协议的⽅法列表
protocol_addProtocol 为⼀个协议遵循另⼀个协议
protocol_addProperty 为协议添加属性
protocol_getProperty 获取协议中的某个属性
protocol_addMethodDescription 为协议添加⽅法描述
protocol_getMethodDescription 获取协议中某⽅法的描述

7.ivar_xxx系列函数(与实例变量相关)

ivar_getName 获取ivar名称
ivar_getTypeEncoding 获取类型编码
ivar_getOffset 获取偏移量

8.sel_xxx系列函数(讨论关于⽅法编号相关)

sel_getName 获取名称
sel_getUid 注册⽅法
sel_registerName 注册⽅法
sel_isEqual 判断⽅法是否相等

3.runtime 日常运用解决问题=

1.利用关联对象给 分类添加属性
2.遍历类的所有成员变量(修改textField的占位符颜色等,字典转模型,自动归档解档)
3.利用消息转发机制解决找不到方法奔溃问题

4.runtime 常用代码演练

1.简单的字典转模型

+ (instancetype)fan_objectWithJson:(NSDictionary *)json
{
    id obj = [[self alloc] init];
    
    unsigned int count;
    Ivar *ivars = class_copyIvarList(self, &count);
    for (int i = 0; i < count; i++) {
        // 取出i位置的成员变量
        Ivar ivar = ivars[i];
        NSMutableString *name = [NSMutableString stringWithUTF8String:ivar_getName(ivar)];
        [name deleteCharactersInRange:NSMakeRange(0, 1)];
        
        // 设值
        id value = json[name];
        if ([name isEqualToString:@"ID"]) {
            value = json[@"id"];
        }
        [obj setValue:value forKey:name];
    }
    free(ivars);
    
    return obj;
}

2.简单的获取成员变量

    unsigned int count;
    Ivar *ivars = class_copyIvarList([UITextField class], &count);
    for (int i = 0; i < count; i++) {
        // 取出i位置的成员变量
        Ivar ivar = ivars[i];
        NSLog(@"%s %s", ivar_getName(ivar), ivar_getTypeEncoding(ivar));
    }
    free(ivars);

3.简单的替换方法

// 这个是 Person里面的方法
- (void)run
{
    NSLog(@"%s", __func__);
}

// 这个是 myrun 方法
void myrun()
{
    NSLog(@"---myrun");
}

// 这个提替换Person类对象中的run方法的imp 为block
   class_replaceMethod([Person class], @selector(run), imp_implementationWithBlock(^{
        NSLog(@"123123");
    }), "v");

// 这个是直接替换函数的实现
  class_replaceMethod([MJPerson class], @selector(run), (IMP)myrun, "v");
    
    [person run];

你可能感兴趣的:(11.runtime 理解 和 常用点)