关于Class之深入Class
問(wèn)題
以下代碼輸出結(jié)果是什么?
BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];BOOL res3 = [(id)[Sark class] isKindOfClass:[Sark class]];BOOL res4 = [(id)[Sark class] isMemberOfClass:[Sark class]];BOOL res5 = [(id)[[NSObject alloc] init] isKindOfClass:[NSObject class]];BOOL res6 = [(id)[[NSObject alloc] init] isMemberOfClass:[NSObject class]];BOOL res7 = [(id)[[Sark alloc] init] isKindOfClass:[Sark class]];BOOL res8 = [(id)[[Sark alloc] init] isMemberOfClass:[Sark class]];NSLog(@"%d %d %d %d %d %d %d %d", res1, res2, res3, res4,res5,res6,res7,res8);//Sark繼承于NSObject 復(fù)制代碼現(xiàn)在我們來(lái)一步一步解析上述代碼:
isKindOfClass & isMemberOfClass
蘋(píng)果官方文檔對(duì)isKindOfClass的解釋是:
Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class.
gnustep中給出的實(shí)現(xiàn)代碼為:
/*** Returns YES if aClass is the NSObject class*/ + (BOOL) isKindOfClass: (Class)aClass {if (aClass == [NSObject class])return YES;return NO; } /*** Returns YES if the class of the receiver is either the same as aClass* or is derived from (a subclass of) aClass.*/ - (BOOL) isKindOfClass: (Class)aClass {Class class = object_getClass(self);return GSObjCIsKindOf(class, aClass); } 復(fù)制代碼對(duì)isMemberOfClass的解釋是:
Returns a Boolean value that indicates whether the receiver is an instance of a given class.
gnustep中給出的實(shí)現(xiàn)代碼為:
/*** Returns YES if aClass is the same as the receiving class.*/ + (BOOL) isMemberOfClass: (Class)aClass {return (self == aClass) ? YES : NO; } /*** Returns YES if the class of the receiver is aClass*/ - (BOOL) isMemberOfClass: (Class)aClass {return ([self class] == aClass) ? YES : NO; } 復(fù)制代碼其中class方法的實(shí)現(xiàn)為
/*** Returns the receiver.*/ + (Class) class {return self; } /*** Returns the class of which the receiver is an instance.<br />* The default implementation returns the actual class that the* receiver is an instance of.<br />* NB. When NSZombie is enabled (see NSDebug.h) this is changed* to be the NSZombie class upon object deallocation.*/ - (Class) class {return object_getClass(self); } 復(fù)制代碼看到這里我們應(yīng)該對(duì)這兩個(gè)函數(shù)的意思很明白了。
isKindOfClass 判斷的是該對(duì)象是否是該類以及該類子類的實(shí)例。
isMemberOfClass 判斷的是該對(duì)象是否是該類的實(shí)例。
現(xiàn)在我們來(lái)看看object和class的內(nèi)部結(jié)構(gòu)(有刪減):
/// An opaque type that represents an Objective-C class. typedef struct objc_class *Class;/// Represents an instance of a class. struct objc_object {Class isa; };/// A pointer to an instance of a class. typedef struct objc_object *id;struct objc_class {Class isa; // 指向metaclassClass super_class ; // 指向其父類const char *name ; // 類名long version ; // 類的版本信息,初始化默認(rèn)為0,可以通過(guò)runtime函數(shù)class_setVersion和class_getVersion進(jìn)行修改、讀取long info; // 一些標(biāo)識(shí)信息,如CLS_CLASS (0x1L) 表示該類為普通 class ,其中包含對(duì)象方法和成員變量;CLS_META (0x2L) 表示該類為 metaclass,其中包含類方法;long instance_size ; // 該類的實(shí)例變量大小(包括從父類繼承下來(lái)的實(shí)例變量);struct objc_ivar_list *ivars; // 用于存儲(chǔ)每個(gè)成員變量的地址struct objc_method_list **methodLists ; // 與 info 的一些標(biāo)志位有關(guān),如CLS_CLASS (0x1L),則存儲(chǔ)對(duì)象方法,如CLS_META (0x2L),則存儲(chǔ)類方法;struct objc_cache *cache; // 指向最近使用的方法的指針,用于提升效率;struct objc_protocol_list *protocols; // 存儲(chǔ)該類遵守的協(xié)議}復(fù)制代碼由此可知,在OC中,類也是一個(gè)對(duì)象都是一個(gè)含有isa指針的結(jié)構(gòu)體。 其中isa指向所屬Class, super_class指向父類別。
根據(jù)上面的gnustep源碼,我們知道:isKindOfClass的實(shí)現(xiàn)是通過(guò)比較isa指針是否指向同一個(gè)類(元類),如果不是就比較父類的isa指針,直到isa指向了NSObject的isa,如果還未相等就返回NO。 isMemberOfClass的實(shí)現(xiàn)是通過(guò)比較isa指針是否指向同一個(gè)類(元類),如果相同就返回YES。
那么此時(shí)答案就很顯然了:1 0 0 0 1 1 1 1
參考資料: gnustep源碼、 深入理解Class
轉(zhuǎn)載于:https://juejin.im/post/5a31450ef265da43085e0808
總結(jié)
以上是生活随笔為你收集整理的关于Class之深入Class的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于获取客户端Mac地址
- 下一篇: iOS之多线程 2