筆記01

1葛虐、objc_object屿脐、objc_class摄悯、class_rw_t愧捕、class_ro_t次绘、cache_t邮偎、bucket_t禾进、method_t泻云、protocol_t、ivar_t卸夕、property_t

  • objc_class 結(jié)構(gòu)體繼承自objc_object
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;          // objc_class類(lèi)型的指針,指向父類(lèi)的objc_class結(jié)構(gòu)體
    cache_t cache;             // 方法緩存个初,可增量擴(kuò)展的哈希表
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
}

// 用散列表緩存調(diào)用過(guò)的方法猴蹂,提高方法查詢(xún)速度
struct cache_t {
    struct bucket_t *_buckets; // 可變長(zhǎng)度的結(jié)構(gòu)體數(shù)組
    mask_t _mask;  //  散列表長(zhǎng)度 - 1
    mask_t _occupied; // 已經(jīng)緩存的方法數(shù)量(散列表形式存在覆获,會(huì)空槽)
}

typedef uintptr_t cache_key_t;
using MethodCacheIMP = IMP;
struct bucket_t {
    MethodCacheIMP _imp; // IMP
    cache_key_t _key;  // SEL 
}

class_rw_t = class_data_bits_t & FAST_DATA_MASK;
struct class_rw_t {
    const class_ro_t *ro;         // 編譯時(shí)就確定好的
    method_array_t methods;       // 方法列表 二維數(shù)組
    property_array_t properties;  // 屬性列表 二維數(shù)組
    protocol_array_t protocols;   // 協(xié)議列表 二維數(shù)組
    char *demangledName;          // 類(lèi)名
}

struct class_ro_t {
    uint32_t instanceSize;            // 長(zhǎng)度
    const char * name;                // 類(lèi)名
    method_list_t * baseMethodList;   // 方法列表 一維數(shù)組
    protocol_list_t * baseProtocols;  // 協(xié)議 一維數(shù)組
    const ivar_list_t * ivars;        // 成員變量 一維數(shù)組
    property_list_t *baseProperties;  // 屬性 一維數(shù)組
};

struct method_t {
    SEL name;          // 方法名
    const char *types; // 函數(shù)參數(shù) + 返回值類(lèi)型  
    MethodListIMP imp; // 方法地址
}

struct protocol_t : objc_object {
    const char *mangledName;                // 協(xié)議名
    struct protocol_list_t *protocols;      // 協(xié)議列表
    method_list_t *instanceMethods;         // 實(shí)例方法
    method_list_t *classMethods;            // 類(lèi)方法
    method_list_t *optionalInstanceMethods; // 可選實(shí)例方法
    method_list_t *optionalClassMethods;    // 可選類(lèi)方法
    property_list_t *instanceProperties;    // 實(shí)例屬性
    property_list_t *_classProperties;      // 類(lèi)屬性
    const char *demangledName();
}

struct ivar_t {
    int32_t *offset;    // 地址中的偏移
    const char *name;   // 變量名
    const char *type;   // 變量類(lèi)型
};

struct property_t {
    const char *name;       // 屬性名
    const char *attributes; // 屬性?xún)?nèi)容:strong、weak...
};
  • 編譯后class_data_bits_t 指向的是一個(gè)class_ro_t的地址(只讀)摹量,運(yùn)行時(shí)缨称,通過(guò)realizeClass()函數(shù)將bits指向class_rw_t
  • 初始化類(lèi):realizeClass -> 設(shè)置rw祝迂、ro
// 初始化類(lèi)信息
static Class realizeClass(Class cls) {
    const class_ro_t *ro;
    class_rw_t *rw;
    Class supercls;
    Class metacls;
    bool isMeta; 

    // 是否為空
    if (!cls) return nil;
    // 是否已經(jīng)初始化
    if (cls->isRealized()) return cls;
    assert(cls == remapClass(cls));

    // 取出class中的data
    ro = (const class_ro_t *)cls->data();
    if (ro->flags & RO_FUTURE) {
        // class初始化
        rw = cls->data();
        ro = cls->data()->ro;
        cls->changeInfo(RW_REALIZED|RW_REALIZING, RW_FUTURE);
    } else {
        // 創(chuàng)建class_rw_t
        rw = (class_rw_t *)calloc(sizeof(class_rw_t), 1);
        // 給class_rw_t里面的class_ro_t賦值
        rw->ro = ro;
        // 設(shè)置狀態(tài)
        rw->flags = RW_REALIZED|RW_REALIZING;
        // 給cls->data重新賦值class_rw_t
        cls->setData(rw);
    }

    isMeta = ro->flags & RO_META;
    rw->version = isMeta ? 7 : 0;  // old runtime went up to 6

    supercls = realizeClass(remapClass(cls->superclass));
    metacls = realizeClass(remapClass(cls->ISA()));

    cls->superclass = supercls;
    cls->initClassIsa(metacls);
    cls->setInstanceSize(ro->instanceSize);

    if (supercls) {
        addSubclass(supercls, cls);
    } else {
        addRootClass(cls);
    }

    // 取出class_ro_t中的數(shù)據(jù)睦尽,賦值給class_rw_t
    methodizeClass(cls);
    return cls;
}

  • 初始化類(lèi)后,class_rw_t中的methods型雳、protocols当凡、properties的都是空的,需要在methodizeClass函數(shù)中進(jìn)行賦值纠俭,將class_ro_t中的數(shù)據(jù)取出沿量,賦值給class_rw_t
// 給rw賦值method list、protocol list冤荆、property list
static void methodizeClass(Class cls) {
    bool isMeta = cls->isMetaClass();
    auto rw = cls->data();
    auto ro = rw->ro;

    // Install methods and properties that the class implements itself.
    // 1朴则、把ro中的方法添加到rw中
    method_list_t *list = ro->baseMethods();
    if (list) {
        prepareMethodLists(cls, &list, 1, YES, isBundleClass(cls));
        rw->methods.attachLists(&list, 1);
    }

    // 2、把ro中的屬性添加到rw中
    property_list_t *proplist = ro->baseProperties;
    if (proplist) {
        rw->properties.attachLists(&proplist, 1);
    }
    
    // 3钓简、把ro中的協(xié)議添加到rw中
    protocol_list_t *protolist = ro->baseProtocols;
    if (protolist) {
        rw->protocols.attachLists(&protolist, 1);
    }

    if (cls->isRootMetaclass()) {
        addMethod(cls, SEL_initialize, (IMP)&objc_noop_imp, "", NO);
    }

    // Attach categories.
    // 把分類(lèi)中的方法乌妒、屬性欧宜、協(xié)議添加到類(lèi)中去
    category_list *cats = unattachedCategoriesForClass(cls, true /*realizing*/);
    attachCategories(cls, cats, false /*don't flush caches*/);

    if (cats) free(cats);
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市挂绰,隨后出現(xiàn)的幾起案子重虑,更是在濱河造成了極大的恐慌永高,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艇抠,死亡現(xiàn)場(chǎng)離奇詭異奴拦,居然都是意外死亡绿鸣,警方通過(guò)查閱死者的電腦和手機(jī)擎厢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)厘惦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事缝左。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵馏予,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我悉尾,道長(zhǎng)惫霸,這世上最難降的妖魔是什么翘悉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任制市,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘历葛。我一直安慰自己咒程,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布刺洒。 她就那樣靜靜地躺著渔肩,像睡著了一般周偎。 火紅的嫁衣襯著肌膚如雪钳踊。 梳的紋絲不亂的頭發(fā)上拓瞪,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音航罗,去河邊找鬼屁药。 笑死复亏,一個(gè)胖子當(dāng)著我的面吹牛耕突,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播登刺,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼北救,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荐操!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起珍策,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤托启,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后攘宙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體屯耸,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拐迁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疗绣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片线召。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖多矮,靈堂內(nèi)的尸體忽然破棺而出灶搜,到底是詐尸還是另有隱情,我是刑警寧澤工窍,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站前酿,受9級(jí)特大地震影響患雏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜罢维,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一淹仑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肺孵,春花似錦匀借、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至瑰艘,卻和暖如春是鬼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背紫新。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工均蜜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芒率。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓囤耳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親偶芍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子充择,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容