OC底层原理05 - isa与类关联的原理

2020-12-02  本文已影响0人  H雷610

在探讨这个问题前,我们首先要弄清楚对象的本质什么
编译器clang
clang是一个由Apple主导编写,基于LLVMC/C++/OC的编译器
操作指令

//1、将 main.m 编译成 main.cpp
clang -rewrite-objc main.m -o main.cpp

//2、将 ViewController.m 编译成  ViewController.cpp
clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot / /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.7.sdk ViewController.m

//以下两种方式是通过指定架构模式的命令行,使用Xcode工具 xcrun
//3、模拟器文件编译
- xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 

//4、真机文件编译
- xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 

探索对象本质是什么

  1. main中自定义一个HLPerson类,有一个属性name
@interface HLPerson : NSObject
@property (nonatomic, copy) NSString *name;
@end

@implementation HLPerson
@end
  1. 打开终端,cdmain.m的文件夹,输入clang指令:clang -rewrite-objc main.m -o main.cppmain.m编译成 main.cpp
  2. 打开编译好的main.cpp,搜索HLPerson,找到HLPerson的定义 image.png 我们发现HLPerson在底层被编译成struct结构体,属性name还生成了相应的get方法_I_HLPerson_name以及set方法_I_HLPerson_setName_
    在结构体中,我们看到第一个属性为struct NSObject_IMPL NSObject_IVARS,其实它是继承于NSObject,这种方式属于伪继承,伪继承是直接将结构体定义为HLPerson中的第一个属性,意味着HLPerson拥有该结构体中的所有成员变量
    然后我们搜索NSObject_IMPL
struct NSObject_IMPL {
    Class isa;
};

发现NSObject_IMPL中的第一个属性其实就是isa

总结

objc_setProperty 源码探索

在上面我们看到除了HLPerson底层定义外,还有其属性对应的getset方法,其中set方法其实是依赖于runtimeobjc_setProperty所实现的
接下来我们来看看objc_setProperty的底层原理

总结

所有外层属性的set方法。都会来到objc_setProperty方法,调用了reallySetProperty实现set功能。

image.png
这是一种适配器设计模式(即将底层接口适配为客户端需要的接口),对外提供一个接口,供上层的set方法使用,对内调用底层的set方法,使其相互不受影响,即无论上层怎么变,下层都是不变的,或者下层的变化也无法影响上层,主要是达到上下层接口隔离的目的

构造数据类型

构造数据类型的方式有以下两种:

两者的区别

isa的类型 isa_t

查看objc4-781源码,看到以下isa指针的类型isa_t的定义,从定义中可以看出是通过联合体(union)定义的。

image.png 从isa_t的定义中可以看出:

两种不同的平台isa储存情况如图所示

image.png

原理探索

inline void 
objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
{
    ASSERT(!cls->instancesRequireRawIsa());
    ASSERT(hasCxxDtor == cls->hasCxxDtor());

    initIsa(cls, true, hasCxxDtor);
}

验证isa指针位域

isa 与 类 的关联

clsisa关联原理就是isa指针中的shiftcls位域中存储了类信息,其中initInstanceIsa的过程是将calloc指针和当前的类cls关联起来,可以通过以下几种方式来验证:

方式一:initIsa

方式二:isa & ISA_MSAK

方式三:object_getClass

object_getClass(<#id  _Nullable obj#>)

方式四:位运算

上一篇 下一篇

猜你喜欢

热点阅读