阅读 270

类的动态创建(ro,rw)& 懒加载类和非懒加载类底层加载的区别 & 类和分类的搭配分析

1.一个参数取地址了,一个没有,两种写法是一样的,只是语法不同的问题。

2.元类的递归问题:

通过函数传入,表,isa,如果存在返回cls元类,不存在返回c2是nil

如果没有下标idx,存一份,有则返回NX_,回到第二步骤

3.面试题:类的创建 ro rw

(1)实例:

注意:

1.先添加成员变量再注册内存,如果先注册内存,就会调用changinfo,如下图返回NO,无法继续往下走,无法添加ivar // : 添加成员变量 1<<aligment // ivar - ro - ivarlist class_addIvar(LGPerson, "lgName", sizeof(NSString *), log2(sizeof(NSString *)), "@"); // : 注册到内存 objc_registerClassPair(LGPerson);

    // cls->ISA()->changeInfo(RW_CONSTRUCTED, RW_CONSTRUCTING | RW_REALIZING);
    // cls->changeInfo(RW_CONSTRUCTED, RW_CONSTRUCTING | RW_REALIZING);
复制代码

2.:先添加set,get方法才能调用setValue forKey,否则报错 无法添加进去。 添加setter + getter 方法 class_addMethod(LGPerson, @selector(setSubject:), (IMP)lgSetter, "v@:@"); class_addMethod(LGPerson, @selector(subject), (IMP)lgName, "@@:");

    // 开始使用
    id person = [LGPerson alloc];
    [person setValue:@"KC" forKey:@"lgName"];
    NSLog(@"%@",[person valueForKey:@"lgName"]);
复制代码

ro - rw - 类的动态创建面试题

    // 1: 动态创建类
    Class LGPerson = objc_allocateClassPair([NSObject class], "LGPerson", 0);
    // 2: 添加成员变量 1<<aligment
    // ivar - ro - ivarlist
    class_addIvar(LGPerson, "lgName", sizeof(NSString *), log2(sizeof(NSString *)), "@");
    // 3: 注册到内存
    objc_registerClassPair(LGPerson);
    
    // cls->ISA()->changeInfo(RW_CONSTRUCTED, RW_CONSTRUCTING | RW_REALIZING);
    // cls->changeInfo(RW_CONSTRUCTED, RW_CONSTRUCTING | RW_REALIZING);
   
    // 3.1 添加property - rw
    lg_class_addProperty(LGPerson, "subject");
    lg_printerProperty([LGTeacher class]);
    lg_printerProperty(LGPerson);

    // 3.2 添加setter  +  getter 方法
    class_addMethod(LGPerson, @selector(setSubject:), (IMP)lgSetter, "v@:@");
    class_addMethod(LGPerson, @selector(subject), (IMP)lgName, "@@:");

    // 开始使用
    id person = [LGPerson alloc];
    [person setValue:@"KC" forKey:@"lgName"];
    NSLog(@"%@",[person valueForKey:@"lgName"]);
    
    id teacher = [LGTeacher alloc];
    [teacher setValue:@"iOS" forKey:@"subject"];
    NSLog(@"%@",[teacher valueForKey:@"subject"]);
    
    [person setValue:@"master" forKey:@"subject"];
    NSLog(@"%@",[person valueForKey:@"subject"]);
复制代码

相关api 的注释

 * 创建类对
 *superClass: 父类,传Nil会创建一个新的根类
 *name: 类名
 *extraBytes: 0
 *return:返回新类,创建失败返回Nil,如果类名已经存在,则创建失败
  objc_allocateClassPair(<#Class  _Nullable __unsafe_unretained superclass#>, <#const char * _Nonnull name#>, <#size_t extraBytes#>)
 */


/**
 *添加成员变量
 *
 *cls 往哪个类添加
 *name 添加的名字
 *size 大小
 *alignment 对齐处理方式
 *types 签名
 *
 *这个函数只能在objc_allocateClassPair和objc_registerClassPair之前调用。不支持向现有类添加一个实例变量。
 *这个类不能是元类。不支持在元类中添加一个实例变量。
 *实例变量的最小对齐为1 << align。实例变量的最小对齐依赖于ivar的类型和机器架构。对于任何指针类型的变量,请通过log2(sizeof(pointer_type))。
  class_addIvar(<#Class  _Nullable __unsafe_unretained cls#>, <#const char * _Nonnull name#>, <#size_t size#>, <#uint8_t alignment#>, <#const char * _Nullable types#>)
 */

/**
 *往内存注册类
 *
 * cls 要注册的类
 *
 * objc_registerClassPair(<#Class  _Nonnull __unsafe_unretained cls#>)
 */


/**
 *往类里面添加方法
 *
 *cls 要添加方法的类
 *sel 方法编号
 *imp 函数实现指针
 *types 签名
 *
 *class_addMethod(<#Class  _Nullable __unsafe_unretained cls#>, <#SEL  _Nonnull name#>, <#IMP  _Nonnull imp#>, <#const char * _Nullable types#>)
 */



/**
 *往类里面添加属性
 *
 *cls 要添加属性的类
 *name 属性名字
 *attributes 属性的属性数组。
 *attriCount 属性中属性的数量。
 *
 *class_addProperty(<#Class  _Nullable __unsafe_unretained cls#>, <#const char * _Nonnull name#>, <#const objc_property_attribute_t * _Nullable attributes#>, <#unsigned int attributeCount#>)
 */
复制代码

4.懒加载类和非懒加载类的区别

属非懒加载类直接走上节课的realizeClassWithoutSwift 去加载数据,懒加载类 在lookupimpOrforward 中 有 if (!cls->isRealized())判断条件,如果用到时候没有实现过则进入实现流程,如果实现过则跳过判断,进行下面的流程。 if (!cls->isRealized()) { cls = realizeClassMaybeSwiftAndLeaveLocked(cls, runtimeLock); // runtimeLock may have been dropped but is now locked again }

5.类和分类的搭配分析

1.懒加载类 + 非懒加载分类

主类在发送消息的时候才有 — 但是分类提前了 — 需要加载 —-read_image —addUnattacheCategoryForClass —但是没有实现类 ——prepare_load_methods —提前实现了主类realizeClassWithoutSwift

2.非懒加载类 + 非懒加载分类

readImages — realizeClassWithoutSwift —— methodLizeClass — addUnattacheCategoryForClass —判断主类是否实现了,但是这时候主类已经实现了,if(cls —> isRealize){ remethodizeClass }

加载分类进来

cls —-> demangleName () 用这个,不能用Name addUnattachedCategoryForClass(cat, cls, hi); const char *cname = ro->name; const char *oname = "LGTeacher";//LGTeacher if (cname && (strcmp(cname, oname) == 0)) { // printf("_read_images - _getObjc2ClassList 类名 :%s - %p\n",cname,cls); }

if(cls —> isRealize) { remethodizeClass(cls); classExists == YES; }

分类没有实现load —— 编译处理 — data() —> ro

3.非懒加载类 + 懒加载分类

readImages — realizeClassWithoutSwift —— methodLizeClass — 不需要添加表 ——直接 data() ——> ro

4.懒加载类 + 懒加载分类

消息发送的时候 ——lookupImpOrForward —— realizeClassWithoutSwift —— methodLizeClass — addUnattacheCategoryForClass 不进来 ——直接走data()

关注下面的标签,发现更多相似文章
评论