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

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

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

searchid.jpg

可以看到有兩個(gè)頭文件定義了id類(lèi)型,我們進(jìn)一步打開(kāi)objc.h查看源碼,發(fā)現(xiàn)有一個(gè)預(yù)編譯宏#if !OBJC_TYPES_DEFINED,意思是沒(méi)有定義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

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

typedef struct objc_object *id;

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

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類(lèi)型的isa聯(lián)合體,和一系列操作isa的功能函數(shù),有關(guān)isa和Class在后續(xù)的文章會(huì)討論

id類(lèi)型為什么能接受任意類(lèi)型的對(duì)象賦值

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

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è)在編譯期會(huì)有類(lèi)型檢查,前兩個(gè)編譯器會(huì)報(bào)出類(lèi)型不匹配警告,id類(lèi)型的對(duì)象編譯器會(huì)跳過(guò)類(lèi)型檢查

5、[arr_str count];
6、[arr_dic count];
7、[arr_arr count];
8、[arr_id count];

如上,添加四句代碼后能否通過(guò)編譯?答案是6,7可以通過(guò)編譯,5會(huì)報(bào)No visible @interface for 'NSString' declares the selector 'count',8會(huì)報(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類(lèi)型的對(duì)象,跳過(guò)了編譯器的類(lèi)型檢查,導(dǎo)致編譯器在查詢方法符號(hào)的時(shí)候是在當(dāng)前文件的可訪問(wèn)范圍內(nèi)查找,我們知道Foundation框架里面的容器類(lèi)都實(shí)現(xiàn)了count方法,所以自然不知道用哪個(gè)了,有人會(huì)問(wèn),為什么不是查詢到一個(gè)就返回正確的結(jié)果呢,這是因?yàn)樵诰幾g期,編譯器會(huì)做方法唯一性校驗(yàn),那么如何騙過(guò)編譯器的這種校驗(yàn)?zāi)兀?/h6>

我們?cè)偬砑?行代碼

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)上面方法都可通過(guò)編譯,原因是performSelector方法同樣跳過(guò)了編譯器的類(lèi)型檢查,所以建議少用這種調(diào)用方式,那么上面的四個(gè)方法運(yùn)行時(shí)會(huì)不會(huì)有問(wèn)題呢,答案是不會(huì)有問(wèn)題,這是因?yàn)閷?duì)象的isa指針指向了該對(duì)象的真實(shí)類(lèi)對(duì)象NSArray,自然能通過(guò)消息查找機(jī)制找到的count方法

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

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容