前语

在前三篇文章中,咱们从以下几个视点根究类 OC 政策相关的底层原理。

  • 政策的alloc流程
  • 政策的内存对齐
  • 政策的本质

从本篇文章初步,咱们进入 OC 类的华章,本篇便是第一篇关于 OC 类的初探。本文将从以下几个视点进行根究,下面咱们一起初步吧。

  • 类的底层结构 objc_class 剖析
  • 类的 isa联络链 及 承继联络链
  • 类的数据 class_rw_t 剖析(特征及实例缓存视频变成本地视频办法)

一、类的底层结构 objc_c教程动漫人物lass 剖析

在 政策的本质 这篇文章中根究 Class 时发现,Class 其实是一个 objc_class 指针,那么 objc_class 毕竟是什么呢?其内部结构是怎样的呢?咱们现在就来根究一下。

首要,咱们翻开 libobjc源码,大局查找 struct objc_class 作用如下:

iOS进阶 -- 类的底层初探

能够发测验怀孕的试纸图片一深一浅现在源码中,有多个当地对 struct objc_class 有界说,例如 runtime.h、objc-runtime-old.h、objc-runtime-new.h ,通比照发现 objc-runtime-new.h 才是现在正在运用的界说,其界说的代macoscatalina码如下:

iOS进阶 -- 类的底层初探iOS进阶 -- 类的底层初探

由代码能够发现 objc_class 承继于 objc_object,其包括成员有 ISA(在objc_ob测验郁闷症ject中)、superclass、cache、bits,其测验怀孕的试纸图片一深一浅他均为办法,不会存储在该结构体中,这几个成员的界说的缓存视频代码如下:

    // Class ISA;  // 在objc_objecmacos体系t中教程高中
Class super缓存视频怎样转入本地视频class;  // 父教程诀窍2电影类指针
cache_t cache;             // formerly cache pointer and vtable
class_data_bits_t bi程序员装逼代码ts;    // class_rw测验你的自卑程度_t * plus custom rr/alloc flags

咱们别离剖析测验纸怎样看是否怀孕下这几个成员所占用的巨细及含义:

  • ISA:Classl类型,即一个 objc_cmacos版别lass 指针,占用8个字节,这儿标明 isa 所指向的类
  • superclass:与 ISA 归于同一种类型,故也占用 8 个字节,这儿标明承继测验的父类
  • cache:是一个 cache_t 类型的结构体,标明类的缓存数据,比如缓存的办法等。这一点咱们在后面华章会根究到,本篇就先剖析下 cache 所占用的巨细,其在源码中的界说如下图

iOS进阶 -- 类的底层初探
程序员薪酬一般多少以发现,cache_t 中大部分为 stat教程拼音ic 润饰的成员和函数,别离存储在静态大局区和macos是什么意思代码macos12区,实践占用空间的成员只需 _bucketsAndMaybeMask 和 一个匿名共用体,因此剖析这两个成员的巨细即可缓存的视频怎样保存到本地

_bumacosxcketsAndMaybeMask 为 explicit_atomic<uintptr_t> 类型,其巨细与泛型类教程动漫人物uintptr_t 相同,即为8个字节教程高中。 另一个成员为共用体,其内部包括一个结构体成员和一个指针,巨细均为 8 字节,所以这个共用体成员巨细为 8macosbigsur 字节。故 ca程序员che_t cache 占用巨细为 16 字节。

  • bits: bits 存储缓存视频在手机哪里找类的数据,包括办法、特征、协议等,是本篇文章根究的要点。其内部只包缓存含一个 uintptr_t bits; 成员,故占用巨细测验郁闷程度的问卷为 8 字节。

以上即为 objc_class 内部结构的初步剖析教程网站,下一节咱们来具macosbigsur体剖析一下 ISAsuperclass

二、isa联络链及承继联络链

教程网 objc_clas缓存视频怎样转入本地视频s 的成员中有两个成员都标明类的指向联络即 ISAsuperclass,这两个指向有什么区别呢?本末节咱们就来根macos体系究一下。

2.1教程网 isa 联络链

2.1.1 元类初现

在根究政策本质时,咱们现现已过政策的 isa 找到了政策所属的类,这儿咱们仍然运测验郁闷症的20道题用相同的办法持续根究。首要在 libobjc源码工程中新建一个tartge,这儿为了便当,挑选 macOS下的 command li测验用例ne Tool 即可之后新建一个类 BPPmacos版别erson。在 main.m 的测验办法及作用如下:

iOS进阶 -- 类的底层初探

查询作用能够发现图中 a 进程便是经过 isa 找到政策 person 所属的类的进程。 a 和 b 之间其实做了相同的操作,不过操作的政策换成了 BPPerson 类。可是作用令人惊讶, BPPerso缓存视频n 类指向了一块内存地址,po 该地址得到的作用也是 BPPerson。不过很明显这两个 BPPerson 并不是程序员客栈同一个东西,由于它们的地址并不相同,而经过 c 进程打印的效macos12果看,地址为0x00000001000081c8BPPerson 才是真实的类。那么地址教程诀窍2在线观看0x00000001000081a0BPPerson测验郁闷症 又是什么呢?莫非在内存中 BPPerson 不止一份吗?

为了验证这个问题,咱们写缓存的视频怎样保存到本地一个办法,程序员那么心爱经过比照得到的 Class 来验证一下,代码如下:

void compareBPPersonClass(int a) {
Class class1 = [测验网速BPPerson class];
Class class2 = [BP程序员计算器Person alloc].class;
Class class3 = object_getClass([BPPerson alloc]);
NSLog(@"nnclass1为%@ == 地址%p,nclass2为%缓存的视频怎样保存到本地@ == 地址%p,nclass3为%@ == 地址%p,n", class1, class1, class2, class2, class3, class3);
}

程序员需求什么学历印作用如下:

iOS进阶 -- 类的底层初探

经过这个作用咱们发现 BPPerson 打印的内存地址都是相程序员是做什么的同的,也便是说在内存中 BPPerson 只需一份。咱们在缓存工作时发现了另外教程诀窍2在线观看存在的一份也叫做 BPPerson 的内存,虽然咱们现在无法证明它是什么,教程英文可是咱们能够经过检查Mach-O文件缓存视频,看看是否有两个 Bmacosx是什么文件夹PPerson 的符号。
经过 MachOView 东西翻开工程的Mach-O,并在 Symbol Table 中查找 BPPerson ,作用如下:

iOS进阶 -- 类的底层初探

咱们发现在编译时期,体系就帮咱们生成了一个 METACLASS。那么 ME测验网速TACLASS 的作用是什么呢?其实在前面的根究中,咱们发现政策经过 isa 找到了所属的类,那么类经过 isa 找到的必定也是是自己的所属,可是咱们称之为 元类,即METACLAS程序员S。其实本质上类也是一测验个政策,被称为类政策,类政策的i教程动漫人物sa指缓存视频怎样转入相册向其元类,下一末程序员需求什么学历节,咱们将根究类的isa联络链。

2.1.2 isa联络链的根究

在上一节的根究中,咱们知道了什么叫做元类教程诀窍2,那么政策、类、元类的isamacos是什么意思指向有什么联络呢?本末节咱们接着上一末节的Demo持续根究,前次根究到类的 isa 指向了元类,那么元类的 isa 指向哪里呢?下图是根究作用:

iOS进阶 -- 类的底层初探

  • 图中 a 和 b 与上一末节相同,证明了类的 isa 指向了其元类;
  • c 进程则是对元类做了 a、b 的操作,发现元类的 isa教程拼音 指向了地址为 0x000000010036a0f0NSObject
  • 可是经过 d 进程,咱们发现教程网 NSObject 类的地址为 0x000000010036a140,即测验纸怎样看是否怀孕 0x000000010036a0f0 指向的为 NSObject 的元类,称之为根元类。
  • e进程持续操作了根元类,咱们发现根程序员薪酬一般多少元类的isa 指向仍然是根元类。

由此得出macos12结论:

政策isa -> 类,类isa -> 元类,元类isa -> 根元类,根元类isa -> 根元类自macosx

以上根究还未考虑有子类的情况,咱们创建一个新的类 BPProgramer,承继于 BPPerson。持续依据macos12上述办法根究其 isa 指向,作用如下:

iOS进阶 -- 类的底层初探

  • a、跟 BPPerson 相同,BPProgram教程网站er的isa相同指向自己的元类
  • b、BPProgramer元类的isa指向根元类,不会指向 BPPerson 的元类
  • c、根元类的isa指向自己,这一点不受影响

2.2 承继联络链

根究完isa的指向联络,接下来咱们来根究类的承继联络链。

2.2.1 类的承继联络

首要,依据 BmacosbigsurPProgramerBPPerson写一个函数,代码如程序员下:

void compareSupercmacosmojavelass(void) {
Class class1 = [BPProgramer class];
Class superclass = class_getSuperclassmacosmojave(class1);
Class sSuperclass = class_程序员客栈getSuperclass(superclass);macos体系
Class ssSuperclass = class_getSuperclass(sSupmacosx是什么文件夹erclass);
NSLog(@"BPProgramer == %@n superclass == %@n sSuperclass == %@n ssSuperclass == %@n", class1, superclass, sSuperclass, ssSuperclass);
}

实施作用如下图所示:

iOS进阶 -- 类的底层初探

由图中作用能够看出,类的承继联络为 子类 -> 父类 -> … -&gt缓存视频怎样转入相册; 根类NSObject -> nil

2.测验手机是否被监控2.2 元类的承继联络

类的承继联络就这么简略吗?明显不是,上诉作用并没有包括元类,元类有没有什么特殊情况呢?咱们再写一个元类的办法来根缓存视频在手机哪里找究一下,代码如下:

void compareMetaSuperclass(void) {
// NSObject类
Class class = obj教程的意思ect_getClass([NSObject alloc]);
// NSObject元类
Class me教程taClass = object_getClass(c缓存lass);
// NSObject根元类
Class rootMeta测验手机是否被监控Class = object_getClass(meta缓存视频怎样转入本地视频Class);
// NSObject根根元类
Class rootRootMetaClass = object_getClass(rootMetaClass);
NSLo程序员装逼代码g(@"n%p 类n%p 元类n%p 根元类macos版别n%p 根根元类",class,m缓存是什么意思etaClass,rootMetaClass,rootRootMeta测验郁闷症Class);
// BPPerson元类
Class pMetaClass = object_getClass(BPPerson.class);
Class pmSuperClass = class_getSuperclass(pMeta教程动漫人物Class); //获取到BPPerson元类的父类
NSLog(@"%@ - %p",pmSuperClass,pmSuperClass)缓存视频怎样转入本地视频;
// BPProgramer程序员那么心爱 -> BPPer缓存视频son -> NSObjecmacos版别t
Class proMetaClass = object_getClass(BPProgramer.clas测验s);测验
Class promSuperClass = class_getSuperclass(proMetaClass);//获取到BPProgramer测验纸怎样看是否怀孕缓存类的父类
NSLog(@"%macosx@ - %p",promSuperClass,promSuperClass);
//测验纸怎样看是否怀孕 NSObject 根类特殊情况
Class nsuperClass = cl程序员需求什么学历ass_getSuperclass(NSObject.class);
NSLog(@"%@ - %p",nsuperClass,nsuperClass);
// 根元类 -> NSOb程序员客栈ject程序员那么心爱
Class rnsuperClass = cl程序员计算器ass_getSuperclass(测验纸怎样看是否怀孕metaClass);
NSLog(@"%@ - %p",rnsuperClass,rnsupemacOSrC缓存是什么意思lass程序员怎样学);
}

代码实施作用如下程序员是学什么专业

iOS进阶 -- 类的底层初探

上图效教程诀窍2果中别离打印了NSObject类和元类的地址,能够用于剖析元类承继的毕竟是 NSObject类程序员客栈 仍是 NSObject元类 依据图中作用剖析如下:

  • BPPerson的元类 的父类为 NSObject的元类
  • BPProgramer教程诀窍2的元类 的父类为 BPPerson的元类
  • 根元类 的父类为 NSObject 类,NS教程诀窍2在线观看Object类 的父类为nil

2.3 isa联络及承继联络总结

其实苹果现已很清楚的说明这些联络,如图所示为苹果官方供给的一张解析图:

iOS进阶 -- 类的底层初探

这儿做下总结:

  • 政策之间既没有isa联络,也不存在承继联络
  • isa联络: 政策isa -> 类,类i教程诀窍2在线观看sa -> 元类,元类is测验a -> 根元类, 根元类isa -> 根元类自己
  • 承继联络:分两条线,类:子类 -> 父类测验怀孕的试纸图片一深一浅 -> 根类(NSObject) -> nil;元类:子类元类 -> 父类元类 -> 根元类 -> 根类NSObject -> nil

三、类的数据 clas测验怀孕的试纸图片一深一浅s_rw_t测验工程师 剖析 — 特征及实例办法根究

前两节别离根究程序员那么心爱了类的底层结构以及指向联络链(isa和承继),本节根究底层类结构中存储的数据。这儿所说的数据指的是类的特征、办法、成员变量等信息。

3.1 class_rw_t剖析

在第一节剖析类的程序员装逼代码底层结构时,咱们知道类的数据是存储在 class_data_bits_t bits 中的。在 libobjc源码 中的界说如下:

iOS进阶 -- 类的底层初探

class_data_bits_t bits是一个结构体,只包括了一个成员 uintptr_t bits;,占测验郁闷症的20道题用8个字节。除了 bits 这一成员外,其他便是函数了,在很多函数中我程序员们发现如下两个函数:

iOS进阶 -- 类的底层初探

很明显这是一对 se测验工程师tte缓存文件在哪里r/getter 函数,依据 bits 来修正和取出数据。依据函数的回来值和参数类型,咱们进入 class_rw_t,得到其界说如下:

iOS进阶 -- 类的底层初探iOS进阶 -- 类的底层初探
class_rw_t 中,除了其成员外,咱们发现了几个咱们很熟悉的函数,很明显这便是用来存储类的办法、特征及协议的当地。

3.2 类数据底层存储源码剖析

在上一末节中根究到教程网class_rw_t 是用来存储缓存的视频怎样保存到本地特征、办法、协议的当地,不过详细是怎样存储的还未根究,本末节将以特征为macosmojave例,根究一下源码中是怎样存储的。

在源码中,用来获取特征的函数是缓存文件在哪里 properties() ,其界说代码如下:

// 获取特征,回来值为propertymacoscatalina_array测验你的自卑程度_t
const property_array_t properties() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_r缓存文件在哪里w_ext_t *>(&ro_or_rw_ext)->properties;
} else {
return property_array_t{v.get&l教程诀窍2t;const clmacos是什么意思ass_ro_t *>(&ro_or_rw_ext)->baseProperties};
}
}

咱们发现函数的回来值为 property_array_t,跟进去看一程序员装逼代码下其界说如下:

iOS进阶 -- 类的底层初探

property_array_t 是承继自 list_array_tt,咱们持续跟进去看下,发现其选用的是C++的模板 template 来界说了 list_array_tt,使得咱们能够运用泛型类型,从外部传入咱们需求的类型,其代码如下:

iOS进阶 -- 类的底层初探

咱们能够教程网站教程诀窍2电影注释中看到模板中界说的 Element 是基础元数据类型,List 是元数据的列表类型。在 list_array_tt 中还界说了一个迭代器 iterator 及共用体,别离用来遍历列表和为外界供给一个拜访的 List 接口,代码界说如下:

 protected:
cla测验ss iterator {
const Ptr<List> *lists;
const Ptr<List> *l程序员一分钟毛遂自荐istsEn缓存视频兼并app下载d;
typename List::iterator m, mEnd;
public:
iterator(const Ptr<List> *begin, const Ptr<List> *end)
: lists(begin), listsEnd(end)
{
if (begin != end) {
m = (*begin)->begin();
mEn程序员需求什么学历d = (*begin)->end();
}
}
/*
迭代器 iterator 的其他函数
*/
public:
union {
Ptr<Limacos体系的开发者是st> list; // 供给教程动漫人物给外部调用的接口
uintptr_t arrayAndFlag;
};
/*
其他函数
*/

经过代码能够发现,iteratorprotectd 的,可是其内部函数是 public,所以在外部也能够拜访。其实特征在源码中的macosbigsur存储办法能够简化为如下图所示:
iOS进阶 -- 类的底层初探property_array_t 是最外层的List,property_array_t 包括的是 property_list_t, 而 property_教程诀窍2在线观看list_t 包括教程网 property_t

Tip:这儿对C++中的模板做一下弥补,模板是C++支持参数化多态的东西,运用模板能够运用户为类或许教程英文函数声明一种一般办法,使得类中的某些数据成员或许成员函数的参数、回来值获得恣意类型。运用模板的目的便是能够让程序员编写与类型无关的代码。详细可参照此教程 C++教程。

咱们再回到 property_array_t 的界说,发现咱们传入的 Elementproperty_t 类型,Listproperty_list_t 类型。两部分界说如下:

struct property_t {
const char *n缓存ame;  // 特征称谓
const char *attributes; // 特征的特征,如类型等
};
struct property_list_t : entsize_list_tt<property_t, property_list_t, 0> {
/教程诀窍2/ 这儿是一个空界说,可是承继自 entsize_list_tt
};

pr测验operty_t 的界说简略macos12明了,不需求太多说明,但测验怀孕的试纸图片一深一浅property_list_t 却是一个空的界说教程诀窍2在线观看,不过它承继自 entsize_list_tt,咱们持续跟进去看下,发现其代码如下:

iOS进阶 -- 类的底层初探

咱们发现 entsize_list_tt 也是界说了一个模板,咱们相同能够从外部传入咱们需求的类型。在 entsize_list_tt 内部,咱们发现两个函数如图中红圈所示,能够传入下标 i ,获取到对程序员计算器应的元素,回来值为 Element 的指针。

entsize_list_tt 供给了 get 函数用于拜访元素,不过假如不想调用函数,咱们还能够经过地址偏移的办法来获取,不过步长为 Element 类型的巨细。教程网

以上根究了源码教程网站上是怎缓存视频在手机哪里找样存储特征的,不过在检查的 metho测验手机是否被监控ds()protocols() 后,能够发现
method_array_tprotocol_array_t 也是承继于 list_arr教程拼音ay_tt,所以其存储办法与特征天壤之别,看来这也是运用模程序员那么心爱板的原因。macos版别

3.3 读取特征和实例办法

咱们知道了源码中是怎样教程网站存储特征、办法及协议的,本末节咱们经过 LLDB 指令来读取相关的数据,验证下上一节的结论是否正确。
首要咱们给 BPPerson 和 BPProgramer 增加几个特征和办法,其类界说代码如下图:

iOS进阶 -- 类的底层初探

iOS进阶 -- 类的底层初探

3.3.1 读取特征

咱们先根究下特征怎样获取程序员是做什么的,翻开工程工作如下代码,进行断点调试:
iOS进阶 -- 类的底层初探
BPProg缓存ramer 为例,经过如下进程来进行获取,详细进程及实施作用如下图:

iOS进阶 -- 类的底层初探iOS进阶 -- 类的底层初探
由于作用较长,所以分为2张图,下面咱们剖析下每一进程的含义:

  • p/x BPProgramer.class
    • 16进制打印 BPProgramer 类的首地址
  • p/x 0x0000000100008428 + 0x20
    • 由于 bits 是第四个成员,前面的 isa、s教程诀窍2uperclass、cache共占用缓存视频在手机哪里找32个字节,所以需求类的首地址 + 0x20(32的十六进制),得到 bits
  • p (class_data_bits_t *)0x程序员0000000100008448
    • 强转得到 bits 的指针地址
  • p *$2
    • 取出指针指向的数据 bits
  • p $3.data()
    • 经过data()函数获取到 class_rw_t
  • p *$4
    • 取出指针下的 class_rw_t
  • p $5.properties()
    • 取出特征,教程拼音pr缓存otocol_array_t
  • p $6.list
    • 获取 list,这儿得到的是 RawPt教程r&lt测验怀孕的试纸图片一深一浅;prop测验郁闷症的20道题erty_list_t>
  • p $7.ptr
    • 经过上一步得到的 RawPtr 进一步取到 property_li程序员客栈st_t指针
  • p *$8
    • 获取指针的内容,即 pr程序员装逼代码operty_list_t
  • p 9.get(0)和p9.get(0)和p 9.get(1)
    • 别离获取到 bpmacosxTitlebpLanguage

教程英文过这个macosmojave实施作用,能够发现在实施 *p $8 后得到缓存视频在手机哪里找的 properties 的数量为 2 ,也便是说并不会获测验取到父类的特征,由此得出结论类所存储的特征只是本类的特征,不会存储父类的特征。

BPProgramer 类还包缓存文件在哪里含一个成员变量 programerAge,可是经过 properties() 也未获取到,阐明成员变量并非存储在特征里,这测验网速一点在下一个华章中macos版别会持续根究成员变量的存储位置及怎样获取。

3.3.2 读取办法

其实经过特征的根究,咱们现已了解了获取类的数据的大致进程,关于办法的获取就比较简单上手了。可是与特征又程序员薪酬一般多少一点不同,教程拼音method_t 并非直接取到办法称谓等信息,而教程诀窍2电影是有教程诀窍2一个结构体 big ,如下图所示:

iOS进阶 -- 类的底层初探

在调用 ge测验手机是否被监控t 办法后,需求再调用 big ,才华得到办法信息,详细读取办法缓存视频在手机哪里找的进程和作用如下图:

iOS进阶 -- 类的底层初探

iOS进阶 -- 类的底层初探

获取办法的进程剖析如下

  • 在 p 5.ptr和p∗5.ptr 和 p *6 之前的操作与获取特缓存是什么意思色是相同的
  • 在 p *$6macos是什么意思 之后,作用闪现一共有 5 个办法
  • 之后经过 p 7.get(0).big~p7.get(0).big ~ p 7.get(4).big 获取到办法别离为 [BPProgramacos是什么意思mer bpTitle]、[BPProgr程序员客栈amer bpLanguagmacOSe]、[BPProgramer setB程序员一分钟毛遂自荐pTitle:]、[BPProgramer setBpLan测验工程师guage:]、[BPProgramer .cxx_测验用例destruct]。除了最终一个为析构办法外,其他为特征的 setter缓存视频变成本地视频/getter 办法。至此咱们就获取到了 BPProgramer 办法,可是咱们发现类也是只会存储自己的办法,承继自父类的办法并缓存视频怎样转入相册不会被存储。并且咱们发现没有获取到类办法 + (void)discussWimacos是什么意思thProductManager;,详细是什么原因也留在下一华章继缓存的视频怎样保存到本地续根究。

总结

本篇是类的底层初探,包括了类的结构、类的isa指向联络及承继联络、类的特征及办法的获取,咱们简略总结一下

  • 测验你的自卑程度的结构
    • 类在底层是 objc缓存视频变成本地视频_c缓存lass 结构体,承继于 objc_o教程诀窍2bject,包括四个成员 isa、superclass、cache、bits
  • isa链
    • 测验怀孕的试纸图片一深一浅针isa -> 类,类isa -> 元类,元类isa -> 根元类, 根元类isa -> 根元类自己
  • 承继链
    • 类:子类 -> 父类 -&程序员一分钟毛遂自荐gt; 根类(NSObject缓存视频怎样转入本地视频) -> nil;
    • 元类:子类元类 -> 父类元类 -> 根元类 -> 根类NSObject -> nil
  • 类的特征及办法获取
    • 类的信息存储在 class_教程data_bits_t 中,其内部办法 dat缓存视频兼并app下载a() 会回来一个 class_rw_t 结构体,经过这个结构体能够调用 methods缓存视频怎样转入本地视频、properties()、protocols() 函数,获取到办法、特征、协议的信息。详细的获取办法能够回看第三节。程序员客栈

以上即为关于类的初探,后续还会持续根究类的底层,欢迎咱们持续重视,也希望咱们批评指正。