zoukankan      html  css  js  c++  java
  • 能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么

    不能向编译后得到的类中增加实例变量!

    能向运行时创建的类中添加实例变量!

    因为编译后的类已经注册在runtime中,类结构体中的objc_ivar_list 实例变量的链表和instance_size实例变量的内存大小已经确定,同时runtime 会调用

    class_setIvarLayout 或 class_setWeakIvarLayout来处理strong weak引用,所以不能向存在的类中添加实例变量。

    运行时创建的类是可以添加实例变量,调用 class_addIvar 函数,但是得在调用 objc_allocateClassPair 之后,objc_registerClassPair 之前,原因同上。

    /** 
     * Adds a new instance variable to a class.
     * 
     * @return YES if the instance variable was added successfully, otherwise NO 
     *         (for example, the class already contains an instance variable with that name).
     *
     * @note This function may only be called after objc_allocateClassPair and before objc_registerClassPair. 
     *       Adding an instance variable to an existing class is not supported.
     * @note The class must not be a metaclass. Adding an instance variable to a metaclass is not supported.
     * @note The instance variable's minimum alignment in bytes is 1<<align. The minimum alignment of an instance 
     *       variable depends on the ivar's type and the machine architecture. 
     *       For variables of any pointer type, pass log2(sizeof(pointer_type)).
     */
    OBJC_EXPORT BOOL
    class_addIvar(Class _Nullable cls, const char * _Nonnull name, size_t size, 
                  uint8_t alignment, const char * _Nullable types) 
        OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

    已经编译好的类,调用 class_addIvar 函数,总是会返回 NO ,就是这个原因。

    想返回 YES ,只能在运行时,重新创建一个新类,才可以。

      //在运行时创建继承自NSObject的People类
      Class People = objc_allocateClassPair([NSObject class], "People", 0);
      //添加_name成员变量
      BOOL flag1 = class_addIvar(People, "_name", sizeof(NSString*), log2(sizeof(NSString*)), @encode(NSString*));
      if (flag1) {
          NSLog(@"NSString*类型  _name变量添加成功");
      }
      //添加_age成员变量
      BOOL flag2 = class_addIvar(People, "_age", sizeof(int), sizeof(int), @encode(int));
      if (flag2) {
          NSLog(@"int类型 _age变量添加成功");
      }
      //完成People类的创建
      objc_registerClassPair(People);
      unsigned int varCount;
      //拷贝People类中的成员变量列表
      Ivar * varList = class_copyIvarList(People, &varCount);
      for (int i = 0; i<varCount; i++) {
          NSLog(@"%s",ivar_getName(varList[i]));
      }
      //释放varList
      free(varList);
      //创建People对象p1
      id p1 = [[People alloc]init];
      //从类中获取成员变量Ivar
      Ivar nameIvar = class_getInstanceVariable(People, "_name");
      Ivar ageIvar = class_getInstanceVariable(People, "_age");
      //为p1的成员变量赋值
      object_setIvar(p1, nameIvar, @"张三");
      object_setIvar(p1, ageIvar, @33);
      //获取p1成员变量的值
      NSLog(@"%@",object_getIvar(p1, nameIvar));
      NSLog(@"%@",object_getIvar(p1, ageIvar));

    调用结果

    2021-07-16 13:54:20.021525+0800 Test[6914:114952] NSString*类型  _name变量添加成功
    2021-07-16 13:54:20.021655+0800 Test[6914:114952] int类型 _age变量添加成功
    2021-07-16 13:54:20.021740+0800 Test[6914:114952] _name
    2021-07-16 13:54:20.021810+0800 Test[6914:114952] _age
    2021-07-16 13:54:20.021913+0800 Test[6914:114952] 张三
    2021-07-16 13:54:20.022003+0800 Test[6914:114952] 33
    在北京的灯中,有一盏是我家的。这个梦何时可以实现?哪怕微微亮。北京就像魔鬼训练营,有能力的留,没能力的走……
  • 相关阅读:
    初学java之触发响应事件举例子
    初学java之(盒子分布)
    java(课程设计之记事本界面部分代码公布)
    HDUOJ---1236 排名(浙大考研题)
    HDUOJ----1234 开门人和关门人(浙江大学考研题)
    HDUOJ----2571(命运)(简单动态规划)
    初学java之面板布局的控制
    初学java之常用组件
    初学java之触发响应事件
    课程设计(部分代码)之java版(记事本)
  • 原文地址:https://www.cnblogs.com/huangzs/p/15019745.html
Copyright © 2011-2022 走看看