美文网首页
runtime详解

runtime详解

作者: hard_coder | 来源:发表于2017-03-31 11:55 被阅读0次

    oc的对象以及类的结构?
    首先我们打开 <objc/objc.h> 文件,可以看到如下定义:

    /// An opaque type that represents an Objective-C class.

    typedef struct objc_class *Class;

    /// Represents an instance of a class.

    struct objc_object {

    Class isa OBJC_ISA_AVAILABILITY;

    };

    /// A pointer to an instance of a class.

    typedef struct objc_object * id;

    通过上面定义我们可以看出以下几点:

    我们常用的id类型实际上一个指向objc_object结构体的指针,id通常指代一个对象,也就是说OC对象其实就一个指向objc_object结构体的指针
    我们看objc_object结构体定义,得知其结构体内有一个类型为Class的字段isa,这就是我们常说的isa指针了。
    再来看Class的声明,为一个指向objc_class的指针,
    实际上isa就是指明当前结构体所属类型,我们可以理解为objc_object为Class类型的
    接下来我们继续打开 <objc/runtime.h> ,来看objc_class声明

    struct objc_class {

    Class isa OBJC_ISA_AVAILABILITY;

    if !OBJC2

    Class super_class OBJC2_UNAVAILABLE; // 父类

    const char *name OBJC2_UNAVAILABLE; // 类名

    long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0

    long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识

    long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小

    struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表

    struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表

    struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存

    struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表

    endif

    } OBJC2_UNAVAILABLE;

    下面说一下我们感兴趣的几个字段:

    isa:这里的isa指针同样是一个指向objc_class的指针,表明该Class的类型,这里的isa指针指向的就是我们常说的meta-class了。不难看出,类本身也是一个对象
    super_class:这个指针就是指向该class的super class,即指向父类,如果该类已经是最顶层的根类(如NSObject或NSProxy),则super_class为NULL。
    cache:用于缓存最近使用的方法。一个接收者对象接收到一个消息时,它会根据isa指针去查找能够响应这个消息的对象。在实际使用中,这个对象只有一部分方法是常用的,很多方法其实很少用或者根本用不上。这种情况下,如果每次消息来时,我们都是methodLists中遍历一遍,性能势必很差。这时,cache就派上用场了。在我们每次调用过一个方法后,这个方法就会被缓存到cache列表中,下次调用的时候runtime就会优先去cache中查找,如果cache没有,才去methodLists中查找方法。这样,对于那些经常用到的方法的调用,但提高了调用的效率。
    version:我们可以使用这个字段来提供类的版本信息。这对于对象的序列化非常有用,它可是让我们识别出不同类定义版本中实例变量布局的改变。
    objc_method_list方法链表中存放的是该类的成员方法(-方法),类方法(+方法)存在meta-class的objc_method_list链表中。
    接下来,这里有一个很形象的图来描述相应的继承关系:
    在程序的运行时期可以对类中的内容进行一些操作:
    BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
    cls:被添加方法的类

    name:可以理解为方法名,这个貌似随便起名,比如我们这里叫sayHello2

    imp:实现这个方法的函数

    types:一个定义该函数返回值类型和参数类型的字符串,这个具体会在后面讲

    封装runtime中的方法:
    //用来交换类中的方法的工具类
    +(void)zhSwizzleWithOrigionClass:(Class)origionClass originalSelector:(SEL)originSelector swizzleClass:(Class)swizzleClass swizzleSelector:(SEL)swizzlSelector{
    //原始方法
    Method originMethod = class_getInstanceMethod(origionClass, originSelector);
    //交换后的方法
    Method swizzleMethod = class_getInstanceMethod(swizzleClass, swizzlSelector);
    //查看该类中是否有此方法的实现
    BOOL didAddMethod = class_addMethod(origionClass, originSelector, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
    //如果该类中已经有此方法的实现,那么就给该类中的方法进行替换
    if (didAddMethod) {
    class_replaceMethod(origionClass, swizzlSelector, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));

    }else{
        method_exchangeImplementations(originMethod, swizzleMethod);
    }
    

    }

    //用来判断某个类中是否包含某个实例方法
    +(BOOL)classIsExisitMethod:(Class)methodExisitClass andExisitMehtod:(SEL)exisitMethod{
    return class_respondsToSelector(methodExisitClass,exisitMethod);
    }

    //获取某个类中的所有的实例方法名
    +(NSArray*)getClassAllMethod:(Class)methodClass{
    u_int count;
    NSMutableArray *array = [NSMutableArray array];
    Method *methods= class_copyMethodList([methodClass class], &count);
    for (int i = 0; i < count; i++)
    {
    SEL name = method_getName(methods[i]);
    NSString *strName = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
    [array addObject:strName];
    }
    return array;
    }

    //获取一个类中的类方法
    +(Method)getClassMethodWithClass:(Class)class andSel:(SEL)sel{
    return class_getClassMethod(class,sel);
    }

    //获取一个类中的实例方法
    +(Method)getInstanceMethodWithClass:(Class)class andSel:(SEL)sel{
    return class_getInstanceMethod(class, sel);
    }

    //获取某一个类中的所有的属性
    +(NSArray*)getClassAllProperity:(Class)propertityClass{
    u_int count;
    NSMutableArray *array = [NSMutableArray array];
    objc_property_t properties= class_copyPropertyList([propertityClass class], &count);
    for (int i = 0; i < count;i++)
    {
    const char
    propertyName = property_getName(properties[i]);
    NSString *strName = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
    [array addObject:strName];
    }
    return array;
    }

    相关文章

      网友评论

          本文标题:runtime详解

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