iOS_经验(1)_Runtime_Api查询

作者: 丶纳凉 | 来源:发表于2016-05-11 01:38 被阅读224次

    0丶介绍

    Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时。需要一个运行时系统 (runtime system) 来执行编译后的代码。
    Runtime基本是用C和汇编写的,可见苹果为了动态系统的高效而作出的努力。

    官网文档还提供关于传统和现代版本Runtime的说明
    In the legacy runtime, if you change the layout of instance variables in a class, you must recompile classes that inherit from it.
    In the modern runtime, if you change the layout of instance variables in a class, you do not have to recompile classes that inherit from it.In addition, the modern runtime supports instance variable synthesis for declared properties (see Declared Properties in The Objective-C Programming Language).
    

    一丶Objective-C运行时定义了几种重要的类型。

    -Class:定义Objective-C类
    -Ivar:定义对象的实例变量,包括类型和名字。
    -Protocol:定义正式协议。
    -objc_property_t:定义属性。叫这个名字可能是为了防止和Objective-C1.0中的用户类型冲突,那时候还没有属性。
    -Method:定义对象方法或类方法。这个类型提供了方法的名字(就是**选择器**)、参数数量和类型,以及返回值(这些信息合起来称为方法的**签名**),还有一个指向代码的函数指针(也就是方法的**实现**)。
    -SEL:定义选择器。选择器是方法名的唯一标识符。
    -IMP:定义方法实现。这只是一个指向某个函数的指针,该函数接受一个对象、一个选择器和一个可变长参数列表(varargs),返回一个对象。
    -Class:定义Objective-C类
    -Ivar:定义对象的实例变量,包括类型和名字。
    -Protocol:定义正式协议。
    -objc_property_t:定义属性。叫这个名字可能是为了防止和Objective-C1.0中的用户类型冲突,那时候还没有属性。
    -Method:定义对象方法或类方法。这个类型提供了方法的名字(就是**选择器**)、参数数量和类型,以及返回值(这些信息合起来称为方法的**签名**),还有一个指向代码的函数指针(也就是方法的**实现**)。
    -SEL:定义选择器。选择器是方法名的唯一标识符。
    -IMP:定义方法实现。这只是一个指向某个函数的指针,该函数接受一个对象、一个选择器和一个可变长参数列表(varargs),返回一个对象。
    

    二丶API的速查手册使用

    1.objc_xxx 系列函数

    函数名称函数作用
    objc_getClass获取Class对象
    objc_getMetaClass获取MetaClass对象
    objc_allocateClassPair分配空间,创建类(仅在 创建之后,注册之前 能够添加成员变量)
    objc_registerClassPair注册一个类(注册后方可使用该类创建对象)
    objc_disposeClassPair注销某个类
    objc_allocateProtocol开辟空间创建协议
    objc_registerProtocol注册一个协议
    objc_constructInstance构造一个实例对象(ARC下无效)
    objc_destructInstance析构一个实例对象(ARC下无效)
    objc_setAssociatedObject为实例对象关联对象
    objc_getAssociatedObje*ct获取实例对象的关联对象
    objc_removeAssociatedObjects清空实例对象的所有关联对象
    objc_msgSend发送ObjC消息
    
    **objc_系列函数关注于宏观使用,如类与协议的空间分配,注册,注销等操作**
    

    2.class_xxx 系列函数**

    函数名称函数作用
    class_addIvar为类添加实例变量
    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_conformsToProtocol判断类是否遵循某协议
    class_createInstance创建类的实例
    class_copyIvarList拷贝类的实例变量列表
    class_copyMethodList拷贝类的方法列表
    class_copyProtocolList拷贝类遵循的协议列表
    class_copyPropertyList拷贝类的属性列表
    
    **class_系列函数关注于类的内部,如实例变量,属性,方法,协议等相关问题**
    

    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_getIvar)
    object_setInstanceVariable设置对象中实例变量的值 (ARC中无效,使用object_setIvar)
    
    **objcet_系列函数关注于对象的角度,如实例变量**
    

    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替换方法的实现
    
    -
    **method_系列函数关注于方法内部,如果方法的参数及返回值类型和方法的实现**
    ****
    

    5.property_xxx 系列函数**

    函数名称函数作用
    property_getName获取属性名
    property_getAttributes获取属性的特性列表
    property_copyAttributeList拷贝属性的特性列表
    property_copyAttributeValue拷贝属性中某特性的值
    -
    **property_系类函数关注与属性*内部,如属性的特性等**
    

    6.protocol_xxx 系列函数

    函数名称函数作用
    protocol_conformsToProtocol判断一个协议是否遵循另一个协议
    protocol_isEqual判断两个协议是否一致
    protocol_getName获取协议名称
    protocol_copyPropertyList拷贝协议的属性列表
    protocol_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判断方法是否相等
    

    9.imp_xxx 系列函数

    函数名称函数作用
    imp_implementationWithBlock通过代码块创建IMP
    imp_getBlock获取函数指针中的代码块
    imp_removeBlock移除IMP中的代码块
    

    三丶简单使用

    1. 动态的添加对象的成员变量和方法
    2. 动态交换两个方法的实现
    3. 实现分类也可以添加属性
    4. 实现NSCoding的自动归档和解档
    5. 实现字典转模型的自动转换
    

    //1.检查是否有某个属性或变量

    - (BOOL)hasAttribute:(NSString *)attName
    {
        BOOL flag = NO;
        u_int count;
        Ivar *ivars = class_copyIvarList([self class], &count);
        for (int i = 0; i < count; i++)
        {
            const char *propertyName = ivar_getName(ivars[i]);
            NSString *strName = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
            if ([attName isEqualToString:strName])
            {
                flag = YES;
            }
            NSLog(@"===>%@", strName);
        }
        return flag;
    }
    

    //2.获取属性列表

    unsigned int count;
    objc_property_t *propertyList = class_copyPropertyList([self class], &count);
    for (unsigned int i = 0; i< count; i++)
    {
        const char *name = property_getName(propertyList[i]);
        NSLog(@"__%@",[NSString stringWithUTF8String:name]);
        
        //得到属性的各种信息
        { //得到属性的各种信息
            objc_property_t property = propertyList[i];
            const char *a = property_getAttributes(property);
            NSLog(@"属性信息__%@",[NSString stringWithUTF8String:a]);
        }
    }
    

    //3.交换2个方法

    第一种:
    Method oldMethod1 = class_getInstanceMethod([self class], @selector(viewDidLoad));
    Method newMethod1 = class_getInstanceMethod([self class], @selector(xzbViewDidLoad));
    method_exchangeImplementations(oldMethod1, newMethod1);
    第二种:
    Method oldMethod1 = class_getInstanceMethod([self class], @selector(viewDidLoad));
    Method newMethod1 = class_getInstanceMethod([self class], @selector(xzbViewDidLoad));
    method_setImplementation(oldMethod1, method_getImplementation(newMethod1));
    

    //4.创建一个新类:objc_allocateClassPair

    
    //创建一个新类:objc_allocateClassPair
    Class newClass = objc_allocateClassPair([UIView class], "XZBCustomView", 0);
    //给类增加新的方法:class_addMethod
    class_addMethod(newClass, @selector(report), (IMP)ReportFunction, "v@:");
    //注册新类:objc_registerClassPair
    objc_registerClassPair(newClass);
    
    //实例;
    id instanceOfNewClass = [[newClass alloc] init];
    //调用report
    [instanceOfNewClass performSelector:@selector(report)];
    
    void ReportFunction(id self, SEL _cmd)
    {
        NSLog(@"This object is %p",self);//This object is 0x7fb2d2e0f900
        NSLog(@"Class is %@,and super is %@",[self class],[self superclass]);// Class is XZBCustomView,and super is UIView
        Class currenClass = [self class];
        for (int i = 0; i<5; i++)
        {
            NSLog(@"%d  %p",i,currenClass);
            //获取isa指针指向的对象object_getClass
            currenClass = object_getClass(currenClass);
            NSLog(@"NSObject:%p",[NSObject class]);
            NSLog(@"object_getClass:%p",object_getClass([NSObject class]));
            
        }
    }
    

    四丶扩展

    相关文章

      网友评论

        本文标题:iOS_经验(1)_Runtime_Api查询

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