一、isKindOfClass、isMemberOfClass 作用分別是什么
isKindOfClass方法的作用是判斷一個(gè)對(duì)象是否為指定類或指定類的子類的實(shí)例。如果是,返回YES;否則,返回NO。該方法會(huì)遞歸地向上檢查對(duì)象所屬的父類,直到父類為根類NSObject(或派生自NSObject的類)為止。isMemberOfClass方法的作用是判斷一個(gè)對(duì)象是否為指定類的實(shí)例。如果是,返回YES;否則,返回NO。
isKindOfClass:
類方法:元類 –> 根元類 –> 根類 –> nil 與 傳入類的對(duì)比實(shí)例方法:對(duì)象的類 –> 父類 –> 根類 –> nil 與 傳入類的對(duì)比isMemberOfClass:
類方法:?類的元類與傳入類對(duì)比實(shí)例方法:對(duì)象的父類與傳入類對(duì)比不同的指向:
isa的指向:對(duì)象的 isa 指向類; 類的 isa 指向元類;元類的 isa 指向根元類;根元類的 isa 指向自己。類的superclass的指向:類的 superclass 指向父類, 父類的 superclass 指向根類 ,根類的superclass 指向nil。元類的superclass的指向:元類的 superclass 指向父類的元類,父元類的 superclass 指向根類的元類根元類的 superclass 指向根類,根類的 superclass 指向 nil。和isKindOfClass不同的是,isMemberOfClass只會(huì)檢查對(duì)象的實(shí)際類型是否與指定類相同,不會(huì)向上檢查其父類。
二、isKindOfClass和isMemberOfClass的區(qū)別
首先看看兩個(gè)方法的蘋果官方解釋:
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. (required)
這個(gè)方法用來判斷一個(gè)對(duì)象是否是指定類或者某個(gè)從該類繼承類的實(shí)例對(duì)象。
isMemberOfClass:Returns a Boolean value that indicates whether the receiver is an instance of a given class. (required)
這個(gè)方法用來判斷一個(gè)對(duì)象是否是指定類的實(shí)例對(duì)象。
兩者區(qū)別:
isKindOfClass 可以判斷某對(duì)象是否是某個(gè)類的實(shí)例對(duì)象,這個(gè)類和這個(gè)類的繼承類都可以判斷;isMemberOfClass只能判斷對(duì)象是否是當(dāng)前類的實(shí)例對(duì)象。isMemberOfClass和isKindOfClass的應(yīng)用舉例:
UIScrollView *scrollView = [[UIScrollView alloc] init];if ([scrollView isKindOfClass:[UIView class]]) { NSLog(@"scrollView is isKindOfClass UIView");}if ([scrollView isKindOfClass:[UIScrollView class]]) { NSLog(@"scrollView is isKindOfClass UIScrollView");}if ([scrollView isMemberOfClass:[UIView class]]) { NSLog(@"scrollView is isMemberOfClass UIView");}if ([scrollView isMemberOfClass:[UIScrollView class]]) { NSLog(@"scrollView isMemberOfClass UIScrollView");}
輸出結(jié)果:
scrollView is isKindOfClass UIView
scrollView is isKindOfClass UIScrollView
scrollView isMemberOfClass UIScrollView
另外需要特別注意的是NSArray、NSMutableArray這樣的類,蘋果官方文檔有這樣一段描述:
在類集群表示的對(duì)象上使用此方法時(shí)要小心。由于類集群的性質(zhì),您返回的對(duì)象可能并不總是您所期望的類型。如果您調(diào)用返回類集群的方法,則該方法返回的確切類型是您可以對(duì)該對(duì)象執(zhí)行的操作的優(yōu)異指示器。例如,如果一個(gè)方法返回一個(gè)指向NSArray對(duì)象的指針,你不應(yīng)該使用這個(gè)方法來查看數(shù)組是否可變,如下面的代碼所示:
// DO NOT DO THIS!if ([myArray isKindOfClass:[NSMutableArray class]]){ // Modify the object}
如果您在代碼中使用這樣的結(jié)構(gòu),您可能會(huì)認(rèn)為修改實(shí)際上不應(yīng)該修改的對(duì)象是可以的。這樣做可能會(huì)給其他希望對(duì)象保持不變的代碼帶來問題。如果接收對(duì)象是一個(gè)類對(duì)象,如果aClass是相同類型的class對(duì)象,此方法返回YES,否則返回NO。
測試結(jié)果:
NSArray *testArray = [[NSArray alloc] init];NSMutableArray *testArray2 = [[NSMutableArray alloc] init];if ([testArray isKindOfClass:[NSArray class]]) { NSLog(@"testArray isKindOfClass of NSArray");}if ([testArray isMemberOfClass:[NSArray class]]) { NSLog(@"testArray isMemberOfClass of NSArray");}if ([testArray2 isKindOfClass:[NSMutableArray class]]) { NSLog(@"testArray2 isKindOfClass of NSMutableArray");}if ([testArray2 isMemberOfClass:[NSMutableArray class]]) { NSLog(@"testArray2 isMemberOfClass of NSMutableArray");}
控制臺(tái)輸出:
testArray isKindOfClass of NSArray
testArray2 isKindOfClass of NSMutableArray
各種查詢得出的結(jié)論是:NSArray、NSMutableArray屬于類簇,使用isMemberOfClass不能取到正確的結(jié)果。原因是:由于類簇的性質(zhì),這類對(duì)象實(shí)際返回的實(shí)例有不確定性。NSArray對(duì)象可能會(huì)在運(yùn)行時(shí)發(fā)現(xiàn)其實(shí)運(yùn)作的是NSCFArray(來自Core Foundation框架(C語言的實(shí)現(xiàn)版本),很多Cocoa對(duì)象都是如此做橋接的)??傊畬?duì)于類簇的判斷要謹(jǐn)慎。
延伸閱讀1:isKindOfClass、isMemberOfClass的用法
不管是isKindOfClass還是isMemberOfClass,在類對(duì)象調(diào)用時(shí),都是與調(diào)用者的元類對(duì)象與傳入?yún)?shù)進(jìn)行判斷,在實(shí)例對(duì)象調(diào)用時(shí),不管是isKindOfClass還是isMemberOfClass,都是與調(diào)用者的類對(duì)象與傳入?yún)?shù)進(jìn)行判斷。isKindOfClass具有繼承關(guān)系,會(huì)沿著superclass遍歷;isMemberOfClass,則沒有繼承關(guān)系,只會(huì)判斷一次。