ios-OC底层 isa,联合体的探究

类的数据结构

image.png

clang 编译

clang -rewrite-objc main.m -o main.cpp 把⽬标⽂件编译成c++⽂件
xcrun -sdk iphonesimulator clang -arch x86_64 -rewrite-objc main.m
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m

clang -rewrite-objc main.m -o main.cpp 把⽬标⽂件编译成c++⽂件
UIKit报错问题
clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot /
Applications/Xcode.app/Contents/Developer/Platforms/
iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk main.m
xcode安装的时候顺带安装了xcrun命令,xcrun命令在clang的基础上进⾏了
⼀些封装,要更好⽤⼀些
xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o
main-arm64.cpp (模拟器)
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp (⼿机)

  • 将main.m 编译成 main.cpp 文件查看源码

image.png

  • 拖至项目中并取消编译。运行

image.png

查看main.cpp文件

image.png

image.png

  • 1.得到 LGPerson类,其实就是一个 LGPerson_IMPL 的结构体

  • 2.struct NSObject_IMPL 也是一个结构体

image.png

  • 3.结构体的继承
struct LGPerson_IMPL {
	struct NSObject_IMPL NSObject_IVARS;
	NSString *_KCName;
};
----------------------------------- 转化
struct LGPerson_IMPL {
	Class isa;
	NSString *_KCName;
};

复制代码

Class

  • Class 是一个 objc_class * 的一个结构体指针
  • id 是一个 objc_objct * 的一个结构体指针

image.png

  • get 和 set
static NSString * _I_LGPerson_KCName(LGPerson * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_LGPerson$_KCName)); }  
static void _I_LGPerson_setKCName_(LGPerson * self, SEL _cmd, NSString *KCName) { (*(NSString **)((char *)self + OBJC_IVAR_$_LGPerson$_KCName)) = KCName; }

self 和 _cmd 是隐藏参数,所以写一个方法时是默认自带了两个隐形参数,这就是为什么我们能在set和get以及其他的方法的作用域中可以直接写self.

get :
return (*(NSString **)((char *)self + OBJC_IVAR_$_LGPerson$_KCName));
self的指针首地址 + 地址偏移量获取值,包装成NSString * 返回
复制代码

联合体

  • 结构体(struct)中所有变量是“共存”的——优点是“有容乃⼤”,
    • 全⾯;缺点是struct内存空间的分配是粗放的,不管⽤不⽤,全分配。
  • 联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”;
    • 但优点是内存使⽤更为精细灵活,也节省了内存空间

ISA 就是一个精细灵活的,也节约了内存空间。

  • 要想学习Runtime,首先要了解它底层的一些常用数据结构,比如isa指针
  • 在arm64架构之前,isa就是一个普通的指针,存储着Class、Meta-Class对象的内存地址
  • 从arm64架构开始,对isa进行了优化,变成了一个共用体(union)结构,还使用位域来存储更多的信息
  • 联合体(共同体)union是什么呢?

源码查看

  • 找到这个isa 这个不是 class 而是一个isa_t

image.png

  • 这个isa_t是一个union

image.png

  • 具体定义在isa.h

image.png

image.png

  • 这些应该就是架构了-不同的架构他的掩码也是不一样的位运算也是不一样的。

image.png

image.png

isa详解-位域

  • nonpointer
    • 0,代表普通的指针,存储着Class、Meta-Class对象的内存地址
    • 1,代表优化过,使用位域存储更多的信息
  • has_assoc
    • 是否有设置过关联对象,如果没有,释放时会更快
  • has_cxx_dtor
    • 是否有C++的析构函数(.cxx_destruct),如果没有,释放时会更快
  • shiftcls
    • 存储着Class、Meta-Class对象的内存地址信息,在nonpointer=1的情况下,在arm64架构中有33位用来存储类指针 (重点)
  • magic
    • 用于在调试时分辨对象是否未完成初始化
  • weakly_referenced
    • 是否有被弱引用指向过,如果没有,释放时会更快。弱引用表。
  • deallocating
    • 对象是否正在释放
  • extra_rc
    • 里面存储的值是引用计数器减1
  • has_sidetable_rc
    • 引用计数器是否过大无法存储在isa中
    • 如果为1,那么引用计数会存储在一个叫SideTable的类的属性中
  • 所以结论就是要想真正知道类的信息其实找的不是isa,而是找isa中的 shiftcls,
  • isa 左移三位,再右移20位 就可以获得shiftcls的数据。

image.png

  • 补充

OC底层->isa、superclass和class的结构

OC底层->isa 详解、位运算、枚举拓展。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享