Category為何不能添加成員變量?

關(guān)于Category的原理查近,參考這篇文章:http://tech.meituan.com/DiveIntoCategory.html

Category的使用場(chǎng)景

  • 可以把類的實(shí)現(xiàn)分開在幾個(gè)不同的文件里面饵隙。這樣做有幾個(gè)顯而易見的好處:
    a)可以減少單個(gè)文件的體積
    b)可以把不同的功能組織到不同的category里
    c)可以由多個(gè)開發(fā)者共同完成一個(gè)類
    d)可以按需加載想要的category
  • 聲明私有方法
  • 模擬多繼承
  • 把framework的私有方法公開

Category到底是不能添加成員變量,還是屬性冒冬?還是都不能添加?

屬性和成員變量的區(qū)別,就不介紹了屋摇。
首先,Category在代碼里添加成員變量是根本編譯不過去的幽邓,而添加屬性是可以編譯通過的炮温,如圖:


FFA05734-5479-4D2F-AC71-78C86C681EC7.png

但是,在Category添加的屬性后牵舵,只會(huì)聲明setter和getter方法茅特,.m文件并未實(shí)現(xiàn)setter和getter方法,會(huì)有黃色預(yù)警棋枕,如圖:


4F9D5BD7-FB97-49BE-9B35-7FC274A4D062.png

而且白修,如果調(diào)用的話,也不會(huì)被賦值重斑,如圖:


035F002C-E200-4F7D-BDF1-EFB56C117583.png

最常見的解決方案就是用runtime手動(dòng)實(shí)現(xiàn)setter和getter方法兵睛,這里就不介紹了。
所以窥浪,剛才那個(gè)問題祖很,Category不能添加成員變量和屬性?就可以有答案了漾脂,不能添加成員變量假颇,可以添加屬性,但是屬性要手動(dòng)實(shí)現(xiàn)setter和getter方法骨稿。

Category為何不能添加成員變量笨鸡,而只能添加方法姜钳?

這要從Category的原理說起,簡(jiǎn)單地說就是通過runtime動(dòng)態(tài)地把Category中的方法等添加到類中(蘋果在實(shí)現(xiàn)的過程中并未將屬性添加到類中形耗,所以屬性僅僅是聲明了setter和getter方法哥桥,而并未實(shí)現(xiàn)),具體請(qǐng)參考http://tech.meituan.com/DiveIntoCategory.html
Objective-C提供的runtime函數(shù)中激涤,確實(shí)有一個(gè)lass_addIvar()
函數(shù)用于給類添加成員變量拟糕,但是文檔中特別說明:

This function may only be called after objc_allocateClassPair and before objc_registerClassPair. Adding an instance variable to an existing class is not supported.

意思是說,這個(gè)函數(shù)只能在“構(gòu)建一個(gè)類的過程中”調(diào)用倦踢。一旦完成類定義送滞,就不能再添加成員變量了。經(jīng)過編譯的類在程序啟動(dòng)后就被runtime加載辱挥,沒有機(jī)會(huì)調(diào)用addIvar犁嗅。程序在運(yùn)行時(shí)動(dòng)態(tài)構(gòu)建的類需要在調(diào)用objc_registerClassPair
之后才可以被使用,同樣沒有機(jī)會(huì)再添加成員變量般贼。
我們?cè)O(shè)想一下如果Objective-C允許動(dòng)態(tài)增加成員變量愧哟,會(huì)發(fā)生什么事情。假設(shè)如下代碼可以執(zhí)行哼蛆。

E6AD8A2E-77C0-4186-AFC0-26C8451F6571.png
MyObject *obj = [[MyObject alloc] init];
// 基類增加一個(gè)4字節(jié)的成員變量someVar
class_addIvar([NSObject class], "someVar", 4, ...);
// 基類增加方法someMethod蕊梧,用到了someVar
class_addMethod([NSObject class], @selector(someMethod), ...);
// 調(diào)用someMethod,修改了someVar
[obj someMethod];
// 訪問子類成員變量腮介,會(huì)發(fā)生什么肥矢?
[obj->students length];

顯然,這樣做會(huì)帶來嚴(yán)重問題叠洗,為基類動(dòng)態(tài)增加成員變量會(huì)導(dǎo)致所有已創(chuàng)建出的子類實(shí)例都無法使用甘改,比如上線后的app,如果用戶手機(jī)系統(tǒng)升級(jí)iOS新版本后灭抑,必須重新編譯提交才能在新版系統(tǒng)上運(yùn)行十艾。那為什么runtime允許動(dòng)態(tài)添加方法和屬性,而不會(huì)引發(fā)問題呢腾节?

因?yàn)榉椒ê蛯傩圆⒉弧皩儆凇鳖悓?shí)例忘嫉,而成員變量“屬于”類實(shí)例。我們所說的“類實(shí)例”概念案腺,指的是一塊內(nèi)存區(qū)域庆冕,包含了isa指針和所有的成員變量。所以假如允許動(dòng)態(tài)修改類成員變量布局劈榨,已經(jīng)創(chuàng)建出的類實(shí)例就不符合類定義了访递,變成了無效對(duì)象。但方法定義是在objc_class中管理的同辣,不管如何增刪類方法拷姿,都不影響類實(shí)例的內(nèi)存布局惭载,已經(jīng)創(chuàng)建出的類實(shí)例仍然可正常使用。

需要注意的有兩點(diǎn):

  • 1)跌前、category的方法沒有“完全替換掉”原來類已經(jīng)有的方法棕兼,也就是說如果category和原來類都有methodA陡舅,那么category附加完成之后抵乓,類的方法列表里會(huì)有兩個(gè)methodA
  • 2)、category的方法被放到了新方法列表的前面靶衍,而原來類的方法被放到了新方法列表的后面灾炭,這也就是我們平常所說的category的方法會(huì)“覆蓋”掉原來類的同名方法,這是因?yàn)檫\(yùn)行時(shí)在查找方法的時(shí)候是順著方法列表的順序查找的颅眶,它只要一找到對(duì)應(yīng)名字的方法蜈出,就會(huì)罷休_,殊不知后面可能還有一樣名字的方法涛酗。

參考:http://quotation.github.io/objc/2015/05/21/objc-runtime-ivar-access.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铡原,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子商叹,更是在濱河造成了極大的恐慌燕刻,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剖笙,死亡現(xiàn)場(chǎng)離奇詭異卵洗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)弥咪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門过蹂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人聚至,你說我怎么就攤上這事酷勺。” “怎么了扳躬?”我有些...
    開封第一講書人閱讀 157,630評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵脆诉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我坦报,道長(zhǎng)库说,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評(píng)論 1 284
  • 正文 為了忘掉前任片择,我火速辦了婚禮潜的,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘字管。我一直安慰自己啰挪,他們只是感情好信不,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著亡呵,像睡著了一般抽活。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锰什,一...
    開封第一講書人閱讀 49,856評(píng)論 1 290
  • 那天下硕,我揣著相機(jī)與錄音,去河邊找鬼汁胆。 笑死梭姓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嫩码。 我是一名探鬼主播誉尖,決...
    沈念sama閱讀 39,014評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼铸题!你這毒婦竟也來了铡恕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,752評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤丢间,失蹤者是張志新(化名)和其女友劉穎探熔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體千劈,經(jīng)...
    沈念sama閱讀 44,212評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡清酥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評(píng)論 2 327
  • 正文 我和宋清朗相戀三年驮樊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了洲守。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片魄缚。...
    茶點(diǎn)故事閱讀 38,687評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖喜滨,靈堂內(nèi)的尸體忽然破棺而出捉捅,到底是詐尸還是另有隱情,我是刑警寧澤虽风,帶...
    沈念sama閱讀 34,347評(píng)論 4 331
  • 正文 年R本政府宣布棒口,位于F島的核電站,受9級(jí)特大地震影響辜膝,放射性物質(zhì)發(fā)生泄漏无牵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評(píng)論 3 315
  • 文/蒙蒙 一厂抖、第九天 我趴在偏房一處隱蔽的房頂上張望茎毁。 院中可真熱鬧,春花似錦、人聲如沸七蜘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橡卤。三九已至扮念,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碧库,已是汗流浹背柜与。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谈为,地道東北人旅挤。 一個(gè)月前我還...
    沈念sama閱讀 46,406評(píng)論 2 360
  • 正文 我出身青樓踢关,卻偏偏與公主長(zhǎng)得像伞鲫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子签舞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評(píng)論 2 349

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉秕脓,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,690評(píng)論 0 9
  • 今天朋友問我:我真佩服你,在一家公司這么長(zhǎng)時(shí)間儒搭。 “你過來你也會(huì)這樣的吠架,因?yàn)槲覀兌加泻闷嫘摹?我13年畢業(yè)后進(jìn)公司...
    呀呀丙閱讀 316評(píng)論 0 1
  • 夸人,講故事搂鲫,提問都要注意細(xì)節(jié)傍药,具體到某個(gè)部分,不要太籠統(tǒng)魂仍。
    kwfs筆記閱讀 207評(píng)論 0 0