OC swizzle方法和分類的加載

分類category

category的介紹

??Category是oc2.0添加的語言特性,它的主要作用是在不改變本類下茂附,動態(tài)地給這個類添加方法,除此之外Category還可以將一個類進行拆分在不同文件下進行管理、甚至可以模擬實現(xiàn)多繼承。若Category添加的方法在基類中已經(jīng)存在手报,則會‘覆蓋’基類的同名方法,這里的覆蓋并不是真正的覆蓋改化,而是在方法列表中取用了第一個同名方法名掩蛤。

分類、類陈肛、父類中實例方法和類方法調(diào)用順序

??分類揍鸟、類和父類的方法調(diào)用順序,在我另外一片關(guān)于iOS底層實現(xiàn)的文章中句旱,分析了類的本質(zhì)和方法存放位置阳藻,不清楚的同學(xué)可以先看下這篇文章,通過之前的分析我們知道方法都是將方法轉(zhuǎn)換成objc_msgSeng(obj,SEL)的形式進行消息發(fā)送的前翎,首先會通過查找obj的isa找到其類對象稚配,然后在類對象的方法列表中查找SEL方法,如果能找到的話就調(diào)用類對象的方法港华,如果類方法中不存在該方法就通過supclass指針找到其父類對象,在它父類對象的方法列表中查找該方法午衰,這樣一層層的查找實例方法立宜,類似的類方法就是去其元類對象找那個查找而已冒萄,流程是一樣的。
??知道了類和父類的方法調(diào)用順序后橙数,我們就好奇category中的方法是怎么調(diào)用的尊流,它的結(jié)構(gòu)體是怎樣的。這里我先給大家打印下category在c語言中的結(jié)構(gòu)體以及項目中寫的真是分類對應(yīng)取值

struct _category_t {
    const char *name;
    struct _class_t *cls;
    const struct _method_list_t *instance_methods;
    const struct _method_list_t *class_methods;
    const struct _protocol_list_t *protocols;
    const struct _prop_list_t *properties;
};
static struct _category_t _OBJC_$_CATEGORY_PQStudent_$_test __attribute__ ((used, section ("__DATA,__objc_const"))) = 
{
    "PQStudent",
    0, // &OBJC_CLASS_$_PQStudent,
    (const struct _method_list_t *)&_OBJC_$_CATEGORY_INSTANCE_METHODS_PQStudent_$_test,
    (const struct _method_list_t *)&_OBJC_$_CATEGORY_CLASS_METHODS_PQStudent_$_test,
    0,
    0,
};

分析結(jié)構(gòu)體灯帮,不難發(fā)現(xiàn)崖技,結(jié)構(gòu)體中有六個字段組成,分別是本類名稱钟哥、本壘的類機構(gòu)體迎献、實例方法列表、類方法列表腻贰、協(xié)議列表吁恍、屬性列表,所以分類是不允許添加成員變量的播演,要想添加屬性冀瓦,必須通過添加關(guān)聯(lián)實現(xiàn)setter和getter方法,然后在加載分類的時候写烤,系統(tǒng)會遍歷分類列表將各個分類的實例方法和類方法插入到類方法列表中和元類方法列表中翼闽,并且會根據(jù)先后編譯順序,以此排列洲炊,所以如果存在同名函數(shù)并不是覆蓋感局,而是取用的時候有先后順序⊙』耄總結(jié)分類蓝厌、類、父類的調(diào)用順序是古徒,先調(diào)用分類中的方法拓提,然后調(diào)用類中的方法最后調(diào)用父類中的方法,分類如果有同名的方法隧膘,后編譯的分類中方法先調(diào)用代态。
??在iOS開發(fā)過程中,分類category可以用來擴展一個類的功能疹吃,讓這個本類功能更強大蹦疑,而使用分類的方式進行管理,在一定前提下會比使用子類方式更好管理萨驶,這個前提是在分類以及其下面的方法命名要規(guī)范歉摧,另外分類不能直接添加成員屬性,如果一定要添加的話可以使用objc_getAssociatedObjectobjc_setAssociatedObject方法綁定get和set方法,這里就不講這兩個方法的使用了叁温。

分類再悼、子類、父類的加載順序

oc在編譯的時候膝但,就會加載所有的類冲九,加載的順序依次是父類->子類->分類,在加載完類后會調(diào)用load方法跟束,我們可以在load方法中打印驗證加載順序莺奸,這里簡單講訴下,load方法的調(diào)用原理冀宴,load方法不同于其他類方法或者實例方法是通過消息機制objc_msgSend進行調(diào)用的灭贷,實際上load方法是直接調(diào)用load所造內(nèi)存指針指向的方法,看源碼可以發(fā)現(xiàn)花鹅,load方法的調(diào)用是遞歸進行的氧腰,在調(diào)用自身之前會先調(diào)用父類的load方法。

2019-02-27 16:36:44.842874+0800 swizzleDemo[13546:18542400] wenpq...本類加載
2019-02-27 16:36:44.843789+0800 swizzleDemo[13546:18542400] wenpq...子類加載
2019-02-27 16:36:44.844219+0800 swizzleDemo[13546:18542400] wenpq...分類加載

load方法只會加載一次刨肃,并且不同于initialize這種懶加載方法古拴,所以load是進行swizzle的很好方法。

swizzle使用方法

為了保證swizzle只執(zhí)行一次真友,所以放在load方法中執(zhí)行黄痪,其中originMethod代表舊方法,newMethod代表新方法盔然,在方法交換前先用class_addMethod添加方法桅打,防止newMethod不存在導(dǎo)致崩潰,class_addMethod方法在newMethod存在的情況下愈案,仍會返回NO.

+ (void)load {
    NSLog(@"wenpq...分類加載");
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method originMethod = class_getInstanceMethod([self class], @selector(work));
        Method newMethod = class_getInstanceMethod([self class], @selector(swizzle_work));
        BOOL addSuccess = class_addMethod([self class], @selector(swizzle_work), method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
        // 如果方法存在挺尾,也會添加失敗
        if (addSuccess) {
            //用剛add的新方法replace舊方法
            class_replaceMethod([self class], @selector(work), method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
        } else {
            method_exchangeImplementations(originMethod, newMethod);
        }
    });
}

- (void)swizzle_work {
    NSLog(@"wenpq...分類work");
    [self swizzle_work];//調(diào)用原來的方法
}

目前只列出swizzle的是使用方法,之后會補充常用使用場景
項目demo地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末站绪,一起剝皮案震驚了整個濱河市遭铺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌恢准,老刑警劉巖魂挂,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異馁筐,居然都是意外死亡涂召,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門敏沉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來果正,“玉大人炎码,你說我怎么就攤上這事〔湛ǎ” “怎么了辅肾?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵队萤,是天一觀的道長轮锥。 經(jīng)常有香客問我,道長要尔,這世上最難降的妖魔是什么舍杜? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮赵辕,結(jié)果婚禮上既绩,老公的妹妹穿的比我還像新娘。我一直安慰自己还惠,他們只是感情好饲握,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蚕键,像睡著了一般救欧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锣光,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天笆怠,我揣著相機與錄音,去河邊找鬼誊爹。 笑死蹬刷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的频丘。 我是一名探鬼主播办成,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼搂漠!你這毒婦竟也來了迂卢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤状答,失蹤者是張志新(化名)和其女友劉穎冷守,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惊科,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡拍摇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了馆截。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片充活。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜂莉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出混卵,到底是詐尸還是另有隱情映穗,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布幕随,位于F島的核電站蚁滋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏赘淮。R本人自食惡果不足惜辕录,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望梢卸。 院中可真熱鬧走诞,春花似錦、人聲如沸蛤高。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽戴陡。三九已至塞绿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間猜欺,已是汗流浹背位隶。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留开皿,地道東北人涧黄。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像赋荆,于是被迫代替她去往敵國和親笋妥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉窄潭,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,719評論 0 9
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹 對...
    cosWriter閱讀 11,103評論 1 32
  • 本文載自: http://blog.csdn.net/a316212802/article/details/49...
    MrLuckyluke閱讀 2,475評論 1 7
  • 本文轉(zhuǎn)自(http://www.reibang.com/p/2e1b3f54b4f3)春宣、(https://www...
    th先生閱讀 3,571評論 0 20
  • 寒假上課第七天月帝,每天都數(shù)著離明天休息還有幾天。倒不是不喜歡上課幽污,而是每天早上六點半起床嚷辅,白天站6小時,晚上備課距误,讀...
    英語老師洪澤榮閱讀 409評論 0 3