讀李峰峰博客筆記之RunTime一些重要的數(shù)據(jù)結(jié)構(gòu)

峰神博客地址

Objective-C和其他靜態(tài)語言的區(qū)別

  • Objective-C將在編譯和鏈接時(shí)期做的事放到運(yùn)行時(shí)來處理
    • 即可以在運(yùn)行時(shí)改變其結(jié)構(gòu)
    • 新的函數(shù)可以在運(yùn)行時(shí)被引進(jìn)
    • 已有的函數(shù)可以被刪除
    • 可以交換兩個(gè)方法的實(shí)現(xiàn)等等

1.OC與 Runtime 系統(tǒng)的交互的三種方式

  • 通過OC源代碼
  • 通過 Foundation 框架的 NSObject 類定義的方法
    • -class返回對(duì)象的類启泣;
    • -isKindOfClass: 和 -isMemberOfClass: 方法檢查對(duì)象是否存在于指定的類的繼承體系中(是否是其子類或者父類或者當(dāng)前類的成員變量)
    • -respondsToSelector: 檢查對(duì)象能否響應(yīng)指定的消息
    • -conformsToProtocol:檢查對(duì)象是否實(shí)現(xiàn)了指定協(xié)議類的方法跃闹;
    • -methodForSelector: 返回指定方法實(shí)現(xiàn)的地址。
  • 3雳窟、通過對(duì) Runtime 庫(kù)函數(shù)的直接調(diào)用

Runtime相關(guān)的術(shù)語及其數(shù)據(jù)結(jié)構(gòu)

1孽水、SEL
  • SEL是selector在 Objc 中的表示(Swift 中是 Selector 類)票腰。selector 對(duì)方法名進(jìn)行包裝,以便找到對(duì)應(yīng)的方法實(shí)現(xiàn)女气。它的數(shù)據(jù)結(jié)構(gòu)是
typedef struct objc_selector *SEL;
  • 獲取SEL的方式有
    • 通過 Objc 編譯器命令@selector()
    • 通過Runtime 系統(tǒng)的 sel_registerName 函數(shù)來獲取一個(gè) SEL 類型的方法選擇器杏慰。
2、id
  • id 是一個(gè)參數(shù)類型炼鞠,它是指向某個(gè)類的實(shí)例的指針缘滥。定義如下
typedef struct objc_object *id;
struct objc_object { 
    Class isa; 
};

以上定義,看到 objc_object 結(jié)構(gòu)體包含一個(gè) isa 指針谒主,根據(jù) isa 指針就可以找到對(duì)象所屬的類

3朝扼、Class
  • 數(shù)據(jù)結(jié)構(gòu)如下:
typedef struct objc_class *Class;
  • Class 其實(shí)是指向 objc_class 結(jié)構(gòu)體的指針。objc_class 的數(shù)據(jù)結(jié)構(gòu)如下:
struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;
 
#if !__OBJC2__
    Class super_class (父類指針)                                                        
    const char *name(類名) 
    /* 我們可以使用這個(gè)字段來提供類的版本信息霎肯。這對(duì)于對(duì)象的序列化非常有用擎颖,它可是讓我們識(shí)別出不同類定義版本中實(shí)例變量布局的改變。 */                                                                
    long version(版本)                                                                        
    long info(信息)                                                                               
    long instance_size(類實(shí)例所占內(nèi)存大小)                                      
    struct objc_ivar_list *ivars(成員變量列表)                                      
    struct objc_method_list **methodLists(方法列表)                          
    struct objc_cache *cache(緩存列表)                                              
    struct objc_protocol_list *protocols(協(xié)議列表)                               
#endif
 
} OBJC2_UNAVAILABLE;
  • struct objc_ivar_list *ivars(成員變量列表)
struct objc_ivar_list {
    int ivar_count                                           OBJC2_UNAVAILABLE;
#ifdef __LP64__
    int space                                                OBJC2_UNAVAILABLE;
#endif
    /* variable length structure */
    struct objc_ivar ivar_list[1] 
 }  
  • Ivar 是表示成員變量的類型观游。
typedef struct objc_ivar *Ivar;
struct objc_ivar {
    char *ivar_name                                          OBJC2_UNAVAILABLE;
    char *ivar_type                                          OBJC2_UNAVAILABLE;
    int ivar_offset                                          OBJC2_UNAVAILABLE;
#ifdef __LP64__
    int space                                                OBJC2_UNAVAILABLE;
#endif
}
  • struct objc_method_list **methodLists(方法列表)
struct objc_method_list {
    /* 我們可以動(dòng)態(tài)修改 *obsolete 的值來添加成員方法 */
    struct objc_method_list *obsolete                        OBJC2_UNAVAILABLE;
 
    int method_count                                         OBJC2_UNAVAILABLE;
#ifdef __LP64__
    int space                                                OBJC2_UNAVAILABLE;
#endif
    /* variable length structure */
    struct objc_method method_list[1]                        OBJC2_UNAVAILABLE;
}
  • Method 代表類中某個(gè)方法的類型
typedef struct objc_method *Method;
 
struct objc_method {
    /* 方法的編號(hào) */
    SEL method_name                                          OBJC2_UNAVAILABLE;
    /* 方法類型 method_types 是個(gè) char 指針搂捧,存儲(chǔ)方法的參數(shù)類型和返回值類型 */
    char *method_types                                       OBJC2_UNAVAILABLE;
    /* 指向了方法的實(shí)現(xiàn),本質(zhì)是一個(gè)函數(shù)指針 */
    IMP method_imp                                           OBJC2_UNAVAILABLE;
}
  • IMP結(jié)構(gòu)
typedef id (*IMP)(id, SEL, ...);

它就是一個(gè)函數(shù)指針懂缕,這是由編譯器生成的允跑。當(dāng)你發(fā)起一個(gè) ObjC 消息之后,最終它會(huì)執(zhí)行的那段代碼,就是由這個(gè)函數(shù)指針指定的聋丝。而 IMP 這個(gè)函數(shù)指針就指向了這個(gè)方法的實(shí)現(xiàn)荤崇。
你會(huì)發(fā)現(xiàn) IMP 指向的方法與 objc_msgSend 函數(shù)類型相同,參數(shù)都包含 id 和 SEL 類型潮针。每個(gè)方法名都對(duì)應(yīng)一個(gè) SEL 類型的方法選擇器,而每個(gè)實(shí)例對(duì)象中的 SEL 對(duì)應(yīng)的方法實(shí)現(xiàn)肯定是唯一的倚喂,通過一組 id和 SEL 參數(shù)就能確定唯一的方法實(shí)現(xiàn)地址每篷。

  • Cache 定義如下
typedef struct objc_cache *Cache
 
struct objc_cache {
    unsigned int mask /* total = mask + 1 */                 OBJC2_UNAVAILABLE;
    unsigned int occupied                                    OBJC2_UNAVAILABLE;
    Method buckets[1]                                        OBJC2_UNAVAILABLE;
};
  • Property定義如下
typedef struct objc_property *Property;
typedef struct objc_property *objc_property_t;//這個(gè)更常用
  • 可以以通過class_copyPropertyList 方法獲取類中的屬性
    objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
  • 返回的是屬性列表,列表中每個(gè)元素都是一個(gè) objc_property_t 指針,方法使用示例如下:
#import <Foundation/Foundation.h>
 
@interface Person : NSObject
 
/** 姓名 */
@property (strong, nonatomic) NSString *name;
 
/** age */
@property (assign, nonatomic) int age;
 
/** weight */
@property (assign, nonatomic) double weight;
 
@end

以上是一個(gè) Person 類端圈,有3個(gè)屬性焦读。讓我們用上述方法獲取類的運(yùn)行時(shí)屬性

unsigned int outCount = 0;
 
    objc_property_t *properties = class_copyPropertyList([Person class], &outCount);
 
    NSLog(@"%d", outCount);
 
    for (NSInteger i = 0; i < outCount; i++) {
        NSString *name = @(property_getName(properties[i]));
        NSString *attributes = @(property_getAttributes(properties[i]));
        NSLog(@"%@--------%@", name, attributes);
    }

打印結(jié)果如下:

2016-12-17 11:27:28.473 test[2321:451525] 3
2016-12-17 11:27:28.473 test[2321:451525] name--------T@"NSString",&,N,V_name
2016-12-17 11:27:28.473 test[2321:451525] age--------Ti,N,V_age
2016-12-17 11:27:28.474 test[2321:451525] weight--------Td,N,V_weight

property_getName 用來查找屬性的名稱,返回 c 字符串舱权。property_getAttributes 函數(shù)挖掘?qū)傩缘恼鎸?shí)名稱和 @encode 類型矗晃,返回 c 字符串

  • 可以以通過protocol_copyPropertyList 方法獲取協(xié)議中的屬性
    objc_property_t *protocol_copyPropertyList(Protocol *proto, unsigned int *outCount)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市宴倍,隨后出現(xiàn)的幾起案子张症,更是在濱河造成了極大的恐慌,老刑警劉巖鸵贬,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俗他,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡阔逼,警方通過查閱死者的電腦和手機(jī)兆衅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嗜浮,“玉大人羡亩,你說我怎么就攤上這事∥H冢” “怎么了畏铆?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)专挪。 經(jīng)常有香客問我及志,道長(zhǎng),這世上最難降的妖魔是什么寨腔? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任速侈,我火速辦了婚禮,結(jié)果婚禮上迫卢,老公的妹妹穿的比我還像新娘倚搬。我一直安慰自己,他們只是感情好乾蛤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布每界。 她就那樣靜靜地躺著捅僵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眨层。 梳的紋絲不亂的頭發(fā)上庙楚,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音趴樱,去河邊找鬼馒闷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛叁征,可吹牛的內(nèi)容都是我干的纳账。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捺疼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼疏虫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起啤呼,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤卧秘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后官扣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體斯议,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年醇锚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哼御。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡焊唬,死狀恐怖恋昼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赶促,我是刑警寧澤液肌,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站鸥滨,受9級(jí)特大地震影響嗦哆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜婿滓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一老速、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凸主,春花似錦橘券、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锋华。三九已至,卻和暖如春箭窜,著一層夾襖步出監(jiān)牢的瞬間毯焕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工磺樱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芥丧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓坊罢,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親擅耽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子活孩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,709評(píng)論 0 9
  • 我們常常會(huì)聽說 Objective-C 是一門動(dòng)態(tài)語言乖仇,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢憾儒?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,192評(píng)論 0 7
  • 前言 runtime其實(shí)在我們?nèi)粘i_發(fā)過程中很少使用到,尤其是像我現(xiàn)在比較初級(jí)的程序猿就更用不到了乃沙。但是去面試很多...
    WolfTin閱讀 622評(píng)論 0 2
  • 轉(zhuǎn)載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 733評(píng)論 0 2
  • 前天女兒應(yīng)約去小朋友家里玩警儒。兩個(gè)小伙伴一起玩训裆,兩個(gè)媽媽一起聊。那個(gè)媽媽說:“我家孩子可羨慕你家孩子了蜀铲。每次都跟我說...
    王亞敏閱讀 639評(píng)論 0 2