OC底层探索(六):类的原理

361 阅读2分钟

runtime的优化

clean memory

  • 是指加载后不会发生改变的内存
  • class_ro_t是属于 clean memory,是只读的
  • clean memory 可以进行移除从而节省更多的空间 image.png

dirty memory

  • 是指在程序运行时会发生更改的内容
  • 类结构一经使用就会变成 dirty memory, 因为运行时会向他写入新的数据
  • dirty memoryclean memory更耗性能
  • 只要进程在运行,他就必须存在
  • dirty memory 被分为两部分,一部分为clean memory

image.png

image.png

成员变量和属性以及编码

image.png

  • 对OC文件用Clang进行编码为C++查看底层的实现
xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
  • 查看C++代码

image.png

  • NSObject_IVRSisa, 也是成员变量的首地址
  • 可以看出属性生成了下划线_成员变量,属性都被注释掉了

image.png

  • 属性还会生成对应的set,get方法

编码

image.png

例如: @16@0:8      -> 表示
@ -> id ,返回值
16 -> 占用的内存
@ -> 参数 id, 0 -> 从0号位置开始
: -> SEL,, 8 -> 从8号位置开始

setter方法的底层原理

  • 当我们赋值copy修饰的nameperson.name = leevi,回调用setName 方法
  • setName 又会调用底层的objc_setProperty, 根据C++的代码我也可以看出
  • setNamesel 定位到 imgp(objc_setProperty)
  • 而用strong 修饰的 则采用的内存平移赋值

image.png

什么时候定位到objc_setProperty

  • 是在编译时,所以我们要通过llvm的源码来查看内部的流程

image.png

image.png

image.png

image.png

  • 可以看出使用copy修饰的话,会走objc_setProperty
  • 默认都是strong 修饰

image.png

image.png

  • 底层调用的是reallySetProperty
  • 普通的赋值都是对新值retain, 旧值releaae
  • attomic 修饰时,加了一个 PeropertyLocks的自旋锁,所以读写比较慢

类方法的存储

image.png

  • +类方法存在元类的class_rw_t
  • 其实类方法就是元类实例方法

类方法存储的ABI方式解析

// 获取类的方法名
void wlwObjc_copyMethodList(Class pClass){
    unsigned int count = 0;
    Method *methods = class_copyMethodList(pClass, &count);
    for (unsigned int i=0; i < count; i++) {
        Method const method = methods[i];
        //获取方法名
        NSString *key = NSStringFromSelector(method_getName(method));
        
        NSLog(@"Method, name: %@", key);
    }
    free(methods);
}

// 打印实例方法
void wlwInstanceMethod_classToMetaclass(Class pClass){
    
    const char *className = class_getName(pClass);
    Class metaClass = objc_getMetaClass(className);
    
    Method method1 = class_getInstanceMethod(pClass, @selector(sayHello));
    Method method2 = class_getInstanceMethod(metaClass, @selector(sayHello));

    Method method3 = class_getInstanceMethod(pClass, @selector(sayHappy));
    Method method4 = class_getInstanceMethod(metaClass, @selector(sayHappy));
    
    NSLog(@"%s - %p-%p-%p-%p",__func__,method1,method2,method3,method4);
}
// 打印类方法
void logClassMethod_classToMetaclass(Class pClass){
    
    const char *className = class_getName(pClass);
    Class metaClass = objc_getMetaClass(className);
    
    Method method1 = class_getClassMethod(pClass, @selector(sayHello));
    Method method2 = class_getClassMethod(metaClass, @selector(sayHello));

//    - (void)sayHello;
//    + (void)sayHappy;
    Method method3 = class_getClassMethod(pClass, @selector(sayHappy));
    Method method4 = class_getClassMethod(metaClass, @selector(sayHappy));
    
    NSLog(@"%s-%p-%p-%p-%p",__func__,method1,method2,method3,method4);
}

// 打印IMP
void logIMP_classToMetaclass(Class pClass){
    
    const char *className = class_getName(pClass);
    Class metaClass = objc_getMetaClass(className);

    IMP imp1 = class_getMethodImplementation(pClass, @selector(sayHello));
    IMP imp2 = class_getMethodImplementation(metaClass, @selector(sayHello));// 0
    // sel -> imp 方法的查找流程 imp_farw
    IMP imp3 = class_getMethodImplementation(pClass, @selector(sayHappy)); // 0
    IMP imp4 = class_getMethodImplementation(metaClass, @selector(sayHappy));

    NSLog(@"%p-%p-%p-%p",imp1,imp2,imp3,imp4);
    NSLog(@"%s",__func__);

}