iOS id類型實(shí)現(xiàn)原理

  • 本文會闡述下面幾個(gè)問題
    1间螟、什么是id類型
    2吴旋、id類型的賦值問題
    3、id類型對象在調(diào)用方法的時(shí)候編譯期和運(yùn)行時(shí)的規(guī)則
    4厢破、NSObject類型與id類型的區(qū)別
    5荣瑟、instancetype與id類型的區(qū)別

查看源碼(源碼版本objc4-781.2)

searchid.jpg

可以看到有兩個(gè)頭文件定義了id類型,我們進(jìn)一步打開objc.h查看源碼摩泪,發(fā)現(xiàn)有一個(gè)預(yù)編譯宏#if !OBJC_TYPES_DEFINED笆焰,意思是沒有定義Objective-C再編譯里面的內(nèi)容

#if !OBJC_TYPES_DEFINED
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;
#endif

再打開objc-private.h查看源碼,就是它了见坑,嗯~沒啥區(qū)別仙辟,所以id類型是一個(gè)結(jié)構(gòu)體指針

typedef struct objc_object *id;

objc_object結(jié)構(gòu)體簡略定義如下:

struct objc_object {
private:
    isa_t isa;

public:

    // ISA() assumes this is NOT a tagged pointer object
    Class ISA();

    // rawISA() assumes this is NOT a tagged pointer object or a non pointer ISA
    Class rawISA();

    // getIsa() allows this to be a tagged pointer object
    Class getIsa();
    ...
};

內(nèi)部定義了isa_t類型的isa聯(lián)合體,和一系列操作isa的功能函數(shù)鳄梅,有關(guān)isa和Class在后續(xù)的文章會討論

id類型為什么能接受任意類型的對象賦值

實(shí)際上OC里面任意類型的對象都能用非繼承體系的對象賦值叠国,如下四個(gè)賦值語句都能順利通過編譯

1、NSString *arr_str = [NSArray new];
2戴尸、NSDictionary *arr_dic = [NSArray new];
3粟焊、NSArray *arr_arr = [NSArray new];
4、id arr_id = [NSArray new];

只是前三個(gè)在編譯期會有類型檢查孙蒙,前兩個(gè)編譯器會報(bào)出類型不匹配警告项棠,id類型的對象編譯器會跳過類型檢查

5、[arr_str count];
6挎峦、[arr_dic count];
7香追、[arr_arr count];
8、[arr_id count];

如上坦胶,添加四句代碼后能否通過編譯透典?答案是6,7可以通過編譯顿苇,5會報(bào)No visible @interface for 'NSString' declares the selector 'count'峭咒,8會報(bào)Multiple methods named 'count' found with mismatched result, parameter type or attributes

重點(diǎn)看下第8行代碼報(bào)的錯(cuò)誤,竟然查詢到多個(gè)同名方法纪岁,編譯器不知道用哪個(gè)凑队,為什么呢?
這是因?yàn)閕d類型的對象幔翰,跳過了編譯器的類型檢查漩氨,導(dǎo)致編譯器在查詢方法符號的時(shí)候是在當(dāng)前文件的可訪問范圍內(nèi)查找西壮,我們知道Foundation框架里面的容器類都實(shí)現(xiàn)了count方法,所以自然不知道用哪個(gè)了叫惊,有人會問款青,為什么不是查詢到一個(gè)就返回正確的結(jié)果呢,這是因?yàn)樵诰幾g期赋访,編譯器會做方法唯一性校驗(yàn),那么如何騙過編譯器的這種校驗(yàn)?zāi)兀?/h6>

我們再添加4行代碼

9缓待、[arr_str performSelector:@selector(count)];
10蚓耽、[arr_dic performSelector:@selector(count)];
11、[arr_arr performSelector:@selector(count)];
12旋炒、[arr_id performSelector:@selector(count)];

發(fā)現(xiàn)上面方法都可通過編譯步悠,原因是performSelector方法同樣跳過了編譯器的類型檢查,所以建議少用這種調(diào)用方式瘫镇,那么上面的四個(gè)方法運(yùn)行時(shí)會不會有問題呢鼎兽,答案是不會有問題,這是因?yàn)閷ο蟮膇sa指針指向了該對象的真實(shí)類對象NSArray铣除,自然能通過消息查找機(jī)制找到的count方法

NSObject類型與id類型的區(qū)別

iOS中NSObject是所有類的根類谚咬,你會說還有個(gè)NSProxy呢,嗯尚粘,這個(gè)也后續(xù)再討論~择卦,id是什么我們上面已經(jīng)討論了,NSObject是一個(gè)OC的類郎嫁,自然在編譯期是要進(jìn)行類型檢查的

instancetype與id類型的區(qū)別

看小標(biāo)題就大概知道了吧秉继,我沒有在instancetype后面添加類型兩個(gè)字,原因是instancetype是編譯器保留的關(guān)鍵字泽铛,只用作函數(shù)返回值使用尚辑,進(jìn)行類型檢查,判斷返回的對象類型是不是當(dāng)前類自己

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盔腔,一起剝皮案震驚了整個(gè)濱河市杠茬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌弛随,老刑警劉巖澈蝙,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異撵幽,居然都是意外死亡灯荧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門盐杂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逗载,“玉大人哆窿,你說我怎么就攤上這事±髡澹” “怎么了挚躯?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長擦秽。 經(jīng)常有香客問我码荔,道長,這世上最難降的妖魔是什么感挥? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任缩搅,我火速辦了婚禮,結(jié)果婚禮上触幼,老公的妹妹穿的比我還像新娘硼瓣。我一直安慰自己,他們只是感情好置谦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布堂鲤。 她就那樣靜靜地躺著,像睡著了一般媒峡。 火紅的嫁衣襯著肌膚如雪瘟栖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天谅阿,我揣著相機(jī)與錄音慢宗,去河邊找鬼。 笑死奔穿,一個(gè)胖子當(dāng)著我的面吹牛镜沽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贱田,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼缅茉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了男摧?” 一聲冷哼從身側(cè)響起蔬墩,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耗拓,沒想到半個(gè)月后拇颅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乔询,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年樟插,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡黄锤,死狀恐怖搪缨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸵熟,我是刑警寧澤副编,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站流强,受9級特大地震影響痹届,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜打月,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一队腐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧僵控,春花似錦香到、人聲如沸鱼冀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽千绪。三九已至充易,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荸型,已是汗流浹背盹靴。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瑞妇,地道東北人稿静。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像辕狰,于是被迫代替她去往敵國和親改备。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

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

  • id 類型是iOS中一種特殊的動(dòng)態(tài)數(shù)據(jù)類型蔓倍,其存在價(jià)值: id是一種通用的對象類型悬钳,她可以用類存儲屬于任何類的對象...
    DDY閱讀 14,092評論 1 12
  • Block作為Objective-C中閉包的實(shí)現(xiàn)在iOS開發(fā)中占有非常重要的地位,尤其是作為回調(diào)(callback...
    NotFunGuy閱讀 749評論 0 4
  • 1.runtime簡介 因?yàn)镺bjc是一門動(dòng)態(tài)語言偶翅,所以它總是想辦法把一些決定工作從編譯連接推遲到運(yùn)行時(shí)默勾。也就是說...
    杰哥ios工程獅閱讀 4,207評論 0 47
  • OC中的id類型 id類型 靜態(tài)類型和動(dòng)態(tài)類型 為什么要有動(dòng)態(tài)類型? id數(shù)據(jù)類型與靜態(tài)類型 1. 靜態(tài)類型和動(dòng)態(tài)...
    SumerZZ100閱讀 1,385評論 0 0
  • id:是一種數(shù)據(jù)類型聚谁; id類型被定義為指向?qū)ο蟮闹羔?這可以從id的定義中看出母剥。id在objc.h中的定義為: ...
    逍遙晨旭閱讀 3,072評論 3 22