面試整理五(Category)

Category的實現(xiàn)原理是什么纤控?

Category編譯之后,底層結(jié)構(gòu)是 struct_category_t 船万,里面存儲著分類的方法刻撒、屬性、協(xié)議信息耿导,在程序運行的時候声怔,runtime會將Category的數(shù)據(jù)合并到類信息中(類對象、元類對象中)

Category的加載處理過程:
1.通過runtime加載某個類的所有Category數(shù)據(jù)
2.把所有Category的方法舱呻、屬性醋火、協(xié)議數(shù)據(jù)合并到一個大數(shù)組中。(后編譯的Category數(shù)據(jù)會放到數(shù)組的前面)
3.將合并后的分類數(shù)據(jù)(方法箱吕、屬性芥驳、協(xié)議),插入到類原來的數(shù)據(jù)前面

Category與Class Extension的區(qū)別是什么茬高?

  • Category是在運行時才會將數(shù)據(jù)合并到類信息中兆旬, Extension是在編譯的時候,他的數(shù)據(jù)就包含在類信息中
  • Category可以為系統(tǒng)類添加分類怎栽,Extension不能
  • Category是有聲明和實現(xiàn)丽猬,Extension直接寫在宿主.m文件宿饱,只有聲明
  • 如果Category聲明了聲明了一個屬性,那么Category只會生成這個屬性的set,get方法的聲明,也就不是會實現(xiàn)

Category中有l(wèi)oad方法嗎?load方法是什么時候調(diào)用的宝鼓?load方法能繼承嗎刑棵?

有l(wèi)oad方法。
load方法會在runtime加載類愚铡、分類的時候調(diào)用
每個類蛉签、分類的+load,在程序運行過程中只調(diào)用一次
調(diào)用順序 :
1.先調(diào)用類的+load方法

  • 按照編譯先后順序調(diào)用(先編譯沥寥,先調(diào)用)
  • 調(diào)用子類的+load之前會先調(diào)用父類的+load

2.在調(diào)用分類的+load

  • 按照編譯先后順序調(diào)用(先編譯碍舍,先調(diào)用)

load方法是可以繼承的,但是一般情況下不會主動調(diào)用load方法邑雅,都是讓系統(tǒng)自動調(diào)用片橡。

注意:+load方法是根據(jù)地址直接調(diào)用,不是經(jīng)過objc_msgSend函數(shù)調(diào)用

load淮野、initialize方法的區(qū)別捧书,它們在Category中調(diào)用的順序,以及出現(xiàn)繼承時骤星,它們之間的調(diào)用過程经瓷?

load、initialize方法的區(qū)別是:
1.調(diào)用方式區(qū)別:
+load是根據(jù)函數(shù)地址直接調(diào)用
+initialize是通過objc_msgSend進行調(diào)用
2.調(diào)用時刻:
+load方法會在runtime加載類洞难、分類的時候調(diào)用(只會調(diào)用一次)
+initialize方法會在類第一次接收到消息時調(diào)用舆吮,每一個類只會initialize一次,如果子類沒有實現(xiàn)+initialize队贱,會調(diào)用父類的+initialize(所以父類的+initialize可能會被調(diào)用多次)
3.調(diào)用順序:
1)+load:
先調(diào)用類的load

  • 按照編譯先后順序調(diào)用(先編譯色冀,先調(diào)用)
  • 調(diào)用子類的+load之前,會先調(diào)用父類的+load
    2)+initialize”
  • 先初始化父類
  • 在初始化子類(可能最終調(diào)用的是父類的initialize方法)

調(diào)用順序:
先調(diào)用父類的initialize柱嫌,在調(diào)用子類的initialize
(先初始化父類锋恬,再初始化子類,每個類只會初始化一次)

+initialize方法會在類第一次接收到消息時調(diào)用编丘。
+initialize是通過objc_msgSend進行調(diào)用的与学,所以有以下特點:

  • 如果子類沒有實現(xiàn)+initialize,會調(diào)用父類的+initialize(所以父類的+initialize可能會被調(diào)用多次)
  • 如果分類實現(xiàn)了+initialize瘪吏,就覆蓋類本身的+initialize調(diào)用

Category能否添加成員變量,如果能蜗巧,如何給Category添加成員變量掌眠?

不能直接給category添加成員變量,但是可以間接實現(xiàn)category有成員變量的效果幕屹。

方法一:給分類添加全局字典

@implementation Person (Test)

NSMutableDictionary *weights_;

+(void)load {
    weights_ = [NSMutableDictionary dictionary];
}

- (void)setWeight:(int)weight {
    NSString *key = [NSString stringWithFormat:@"%p",self];
    weights_[key] = @(weight);
}
- (int)weight {
    NSString *key = [NSString stringWithFormat:@"%p",self];
    return [weights_[key] intValue];
}

@end

缺點:
1.全局字典一直存放在內(nèi)存中不會釋放蓝丙,存在內(nèi)存泄漏問題级遭。
2.每一個person對象的set方法都會同時訪問這個字典,存在線程安全問題渺尘。
3.每次添加一個屬性都需要添加一個字典挫鸽,比較麻煩。

方法二:關(guān)聯(lián)對象

#import "Person+Test.h"
#import <objc/runtime.h>

@implementation Person (Test)

// static const void *nameKey = &nameKey;
//可以使用char類型只占一個字節(jié) 指針類型需要占8個字節(jié)
static const char NameKey;

-(void)setName:(NSString *)name {
//    關(guān)聯(lián)策略
//    objc_AssociationPolicy 對應(yīng)的修飾符
//    OBJC_ASSOCIATION_ASSIGN assign
//    OBJC_ASSOCIATION_RETAIN_NONATOMIC strong, nonatomic
//    OBJC_ASSOCIATION_COPY_NONATOMIC copy, nonatomic
//    OBJC_ASSOCIATION_RETAIN strong, atomic
//    OBJC_ASSOCIATION_COPY copy, atomic
    //設(shè)置關(guān)聯(lián)對象
    objc_setAssociatedObject(self, &NameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name {
    //獲得關(guān)聯(lián)對象
    return objc_getAssociatedObject(self, &NameKey);
}

關(guān)聯(lián)對象的實現(xiàn)原理:

關(guān)聯(lián)對象并不是存儲在被關(guān)聯(lián)對象本身內(nèi)存中
關(guān)聯(lián)對象存儲在全局的統(tǒng)一的一個AssociationManager中
如果關(guān)聯(lián)對象為nil鸥跟,就相當于移除關(guān)聯(lián)對象

關(guān)聯(lián)對象實現(xiàn)原理.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丢郊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子医咨,更是在濱河造成了極大的恐慌枫匾,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拟淮,死亡現(xiàn)場離奇詭異干茉,居然都是意外死亡,警方通過查閱死者的電腦和手機很泊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門角虫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人委造,你說我怎么就攤上這事戳鹅。” “怎么了争涌?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵粉楚,是天一觀的道長。 經(jīng)常有香客問我亮垫,道長模软,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任饮潦,我火速辦了婚禮燃异,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘继蜡。我一直安慰自己回俐,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布稀并。 她就那樣靜靜地躺著仅颇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碘举。 梳的紋絲不亂的頭發(fā)上忘瓦,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音引颈,去河邊找鬼耕皮。 笑死境蜕,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的凌停。 我是一名探鬼主播粱年,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼罚拟!你這毒婦竟也來了台诗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤舟舒,失蹤者是張志新(化名)和其女友劉穎拉庶,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秃励,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡氏仗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了夺鲜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片皆尔。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖币励,靈堂內(nèi)的尸體忽然破棺而出慷蠕,到底是詐尸還是另有隱情,我是刑警寧澤食呻,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布流炕,位于F島的核電站,受9級特大地震影響仅胞,放射性物質(zhì)發(fā)生泄漏每辟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一干旧、第九天 我趴在偏房一處隱蔽的房頂上張望渠欺。 院中可真熱鬧,春花似錦椎眯、人聲如沸挠将。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舔稀。三九已至,卻和暖如春掌测,著一層夾襖步出監(jiān)牢的瞬間内贮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贺归,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓断箫,卻偏偏與公主長得像拂酣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子仲义,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

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