runtime使用篇: class_getIvarLayout 和 class_getWeakIvarLayout

前言:

本篇文章將介紹以下兩個和 Ivar Layout 有關(guān)的函數(shù):
const uint8_t *class_getIvarLayout(Class cls)
const uint8_t *class_getWeakIvarLayout(Class cls)

說明:

介紹Ivar Layout之前舒憾,我們先通過這篇回顧一下實例變量ivar,我們已經(jīng)可以利用ivar_getTypeEncodingivar_getName兩個函數(shù)獲取到變量的類型和名稱。平時我們常寫的屬性如下:

屬性

變量類型和變量名稱可以獲取到了聂喇,但是strong或是weak卻還不知道玄柏。本篇要介紹的這兩個函數(shù)正是解決這個問題的。
這兩個函數(shù)的返回值都是 const uint8_t * 類型饥臂,即uint8_t數(shù)組街佑。uint8_t定義如下:

uint8_t

它本質(zhì)上是unsigned char,一般是指無符號8位整型數(shù)屹徘。一個無符號8位整型數(shù)在16進(jìn)制中是兩位走趋,恰好地,這兩位中的后一位表示了連續(xù)的strong(或weak)類型的實例變量的數(shù)量噪伊,前一位表示連續(xù)的非strong(或weak)類型的實例變量的數(shù)量簿煌。這一句聽著有些抽象,用代碼示例來看看:

初窺:

我們先定義一個類并向類中添加少量的屬性:

// Dog.h 文件
@interface Dog : NSObject

@property (nonatomic, strong) id property_1_s;
@property (nonatomic, weak) id property_2_w;
@property (nonatomic, unsafe_unretained) id property_3_un;
@property (nonatomic, weak) id property_4_w;
@property (nonatomic, strong) id property_5_s;
@property (nonatomic, strong) id property_6_s;
@property (nonatomic, unsafe_unretained) id property_7_un;
@property (nonatomic, strong) id property_8_s;
@property (nonatomic, strong) id property_9_s;
@property (nonatomic, weak) id property_10_w;
@property (nonatomic, weak) id property_11_w;
@property (nonatomic, strong) id property_12_s;

@end

// Dog.m 文件
@implementation Dog

@end

為了接下來打印時方便看是strong鉴吹、weakunsafe_unretained類型姨伟,在屬性的最后加上了sw拙寡、un來區(qū)分授滓。
現(xiàn)在將這兩個函數(shù)用起來,代碼示例如下:

// ViewController.m文件

printf("strong:\n");
const uint8_t *array_s = class_getIvarLayout([Dog class]);
int i = 0;
uint8_t value_s = array_s[i];
while (value_s != 0x0) {
    printf("\\x%02x\n", value_s);
    value_s = array_s[++i];
}

printf("----------\n");

printf("weak:\n");
const uint8_t *array_w = class_getWeakIvarLayout([Dog class]);
int j = 0;
uint8_t value_w = array_w[j];
while (value_w != 0x0) {
    printf("\\x%02x\n", value_w);
    value_w = array_w[++j];
}

Ivar Layout打印結(jié)果如下:

strong:
\x01
\x32
\x12
\x21
----------
weak:
\x11
\x11
\x52
\x10

通過打印結(jié)果解釋剛才那句話:
先說class_getIvarLayout獲取的結(jié)果:
第一個\x01表示一開始有0個非strong類型的實例變量肆糕,這是因為第一個屬性property_1_sstrong類型的般堆,這也正是第二位16進(jìn)制那個數(shù)字1所表示的;
接下來有三個非strong類型的诚啃,兩個strong類型的淮摔,即\x32;
接下來有一個非strong類型的,兩個strong類型的始赎,即\x12;
接下來有兩個非strong類型的和橙,一個strong類型的,即\x21;
這些正好對應(yīng)了聲明的所有的屬性造垛。
同理可以理解class_getWeakIvarLayout獲取的結(jié)果魔招。

進(jìn)階:

剛才在類中添加的屬性都是8字節(jié)(64位系統(tǒng)下)的id類型的,現(xiàn)在再向類中添加如下幾個其他類型的:

// 在剛才的property_12_s屬性后添加
/** ----------我是分割線---------- */
@property (nonatomic, assign) int property_13_int;
@property (nonatomic, assign) short property_14_short;
@property (nonatomic, weak) id property_15_w;
@property (nonatomic, assign) char property_16_char;
@property (nonatomic, strong) id property_17_s;

現(xiàn)在屬性一共是17個五辽。運行程序后Ivar Layout打印結(jié)果如下:

strong:
\x11
\x32
\x12
\x21
\x11
----------
weak:
\x21
\x11
\x52
\x11
\x10

有沒有發(fā)現(xiàn)办斑,這兩個函數(shù)獲取到的Ivar Layout數(shù)字總和都是15,而不是屬性的個數(shù)17杆逗?而且獲取到的strong類型的第一位數(shù)字就和剛才不一樣(本次\x11乡翅,剛才\x01)?我們現(xiàn)在用函數(shù)class_copyIvarList獲取類的實例變量列表罪郊,看看能不能找出原因蠕蚜。在ViewController.m文件中添加如下代碼:

unsigned int count;
Ivar *list = class_copyIvarList([Dog class], &count);
for (int i = 0; i < count; i++) {
    Ivar ivar = list[i];
    const char * ivarName = ivar_getName(ivar);
    NSLog(@"%s", ivarName);
}

本次打印結(jié)果如下:

runtime[10502:809019] _property_16_char
runtime[10502:809019] _property_14_short
runtime[10502:809019] _property_13_int
runtime[10502:809019] _property_1_s
runtime[10502:809019] _property_2_w
runtime[10502:809019] _property_3_un
runtime[10502:809019] _property_4_w
runtime[10502:809019] _property_5_s
runtime[10502:809019] _property_6_s
runtime[10502:809019] _property_7_un
runtime[10502:809019] _property_8_s
runtime[10502:809019] _property_9_s
runtime[10502:809019] _property_10_w
runtime[10502:809019] _property_11_w
runtime[10502:809019] _property_12_s
runtime[10502:809019] _property_15_w
runtime[10502:809019] _property_17_s

可以看到,一開始添加的id類型的12個屬性悔橄,用函數(shù)class_copyIvarList獲取到的順序和自己寫的順序仍然一樣靶累;而后添加的其他類型的屬性腺毫,在實例變量列表中的順序和自己寫的就不一樣了。
用這個實例變量列表再和剛才的Ivar Layout對照--為了檢驗問題是不是由基本數(shù)據(jù)類型的屬性產(chǎn)生的挣柬,我們可以倒序著對照(即從_property_17_s開始):

  • 先倒序?qū)φ?code>strong類型的拴曲,一直到_property_1_s都沒問題,_property_1_s對應(yīng)的是第一個\x11中的后一位1凛忿;而_property_16_char_property_14_short_property_13_int三個實例變量共同對應(yīng)前一位1竞川。
  • 再倒序?qū)φ?code>weak類型的店溢,一直到_property_2_w都沒問題,_property_2_w對應(yīng)的是第一個\x21中的后一位1委乌;而_property_16_char床牧、_property_14_short_property_13_int三個實例變量和_property_1_s共同對應(yīng)前一位2

現(xiàn)在已經(jīng)可以推測出遭贸,問題正是由基本數(shù)據(jù)類型的屬性引起的戈咳。可是為什么呢壕吹?
還記著這篇文章里說到的『字節(jié)對齊』嗎著蛙?在上述實例變量列表中,char耳贬、short踏堡、int類型的三個實例變量在『字節(jié)對齊』下占8位,和一個id類型的實例變量所占字節(jié)數(shù)相同咒劲,而且它們是基本數(shù)據(jù)類型顷蟆,既不是strong也不是weak,因此剛才的Ivar Layout就可以理解了腐魂。
讀者可以再自行添加幾個基本數(shù)據(jù)類型的屬性進(jìn)行驗證帐偎,本文不再贅述。

另外蛔屹,當(dāng)某個屬性是copy類型時削樊,Ivar Layout會把它當(dāng)strong類型進(jìn)行處理。
再者判导,將id類型改成NSString *嫉父、UIView *等類型,獲取結(jié)果也相同眼刃。

總結(jié):

1. 這兩個函數(shù)獲取到的Ivar Layout是和class_copyIvarList函數(shù)獲取到的實例變量列表對應(yīng)的绕辖,但要注意『字節(jié)對齊』;
2. 經(jīng)過測試發(fā)現(xiàn)擂红,當(dāng)一個類中沒有strong類型的實例變量時仪际,用class_getIvarLayout函數(shù)獲取到的結(jié)果為NULL围小,這時如果再像代碼示例中array_s[i]獲取角標(biāo)為0的uint8_t類型數(shù)據(jù)時,會直接crash树碱。class_getWeakIvarLayout如是肯适。所以嚴(yán)謹(jǐn)?shù)貞?yīng)該先判斷獲取到的是否為空。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末成榜,一起剝皮案震驚了整個濱河市框舔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赎婚,老刑警劉巖刘绣,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異挣输,居然都是意外死亡纬凤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門撩嚼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來停士,“玉大人,你說我怎么就攤上這事完丽×导迹” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵舰涌,是天一觀的道長猖任。 經(jīng)常有香客問我,道長瓷耙,這世上最難降的妖魔是什么朱躺? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮搁痛,結(jié)果婚禮上长搀,老公的妹妹穿的比我還像新娘。我一直安慰自己鸡典,他們只是感情好源请,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著彻况,像睡著了一般谁尸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上纽甘,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天良蛮,我揣著相機與錄音,去河邊找鬼悍赢。 笑死决瞳,一個胖子當(dāng)著我的面吹牛货徙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播皮胡,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼痴颊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了屡贺?” 一聲冷哼從身側(cè)響起蠢棱,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎甩栈,沒想到半個月后裳扯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡谤职,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了亿鲜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片允蜈。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蒿柳,靈堂內(nèi)的尸體忽然破棺而出饶套,到底是詐尸還是另有隱情,我是刑警寧澤垒探,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布妓蛮,位于F島的核電站,受9級特大地震影響圾叼,放射性物質(zhì)發(fā)生泄漏蛤克。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一夷蚊、第九天 我趴在偏房一處隱蔽的房頂上張望构挤。 院中可真熱鬧,春花似錦惕鼓、人聲如沸筋现。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矾飞。三九已至,卻和暖如春呀邢,著一層夾襖步出監(jiān)牢的瞬間洒沦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工驼鹅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留微谓,地道東北人森篷。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像豺型,于是被迫代替她去往敵國和親仲智。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

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