iOS中的 isKindOfClass 和 isMemberOfClass
先來看一個爛大街的面試題:
下面程式碼結果如何?
BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res3 = [(id)[TestObject class] isKindOfClass:[TestObject class]];
BOOL res4 = [(id)[TestObject class] isMemberOfClass:[TestObject class]];
答案:除了第一個是YES,其他三個都是NO。
在推測結果之前,首先要明白兩個問題。isKindOfClass
和 isMemberOfClass
的區別是什麼?
isKindOfClass:
returns YES if the receiver is an instance of the specified class or an instance of any class that inherits from the specified class.
方法呼叫者是傳入的類的例項物件,或者呼叫者是傳入類的繼承者鏈中的類的例項物件,則返回YES。
isMemberOfClass:
returns YES if the receiver is an instance of the specified class.
方法呼叫者必須是傳入的類的例項物件才返回YES。
我們從Runtime原始碼的角度來分析一下結果。
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->super_class) {
if(tcls == cls) return YES;
}
return NO;
}
-(BOOL)isKindOfClass:(Class)cls {
for(Class tcls = [self class]; tcls; tcls = tcls->super_class) {
if(tcls == cls) return YES;
}
return NO;
}
平時開發過程中只會接觸到物件方法的isKindOfClass
和isMemberOfClass
,但是在NSObject
類中還隱式的實現了類方法版本。不只這兩個方法,其他NSObject
中的物件方法,都有其對應的類方法版本。因為在OC中,類和元類也都是物件。這四個呼叫由於都是類物件發起呼叫的,所以最終執行的都是類方法版本。
先把Runtime的物件模型拿出來,方便後面的分析。
因為呼叫類的class
方法,會把類自身直接返回,所以第一次呼叫者是NSObject
類物件,+ (BOOL)isKindOfClass:(Class)cls
方法的引數cls
也是NSObject
類物件。
進入到for
迴圈中,在此說明一下object_getClass()
方法相當於取出isa
指標指向的類,所以會從NSObject
的元類開始遍歷,所以第一次NSObject meta class != NSObject class
,匹配失敗。第二次迴圈將tcls
設定為superclass
的NSObject class
,NSObject class==NSObject class
,匹配成功。
NSObject
能匹配成功,是因為這個類比較特殊,在第二次獲取 superClass
的時候,NSObject
元類的superClass
就是NSObject
的類物件,所以會匹配成功。而其他三種匹配,則都會失敗,各位同學可以去自己分析一下剩下三種。
參考資料
相關文章
- iOS中isKindOfClass和isMemberOfClass的區別iOS
- iOS isKindOfClass與isMemberOfClass的區別iOS
- isKindOfClass和isMemberOfClass的區別
- isMemberOfClass、isKindOfClass原理分析
- iOS中的isEqual和hashiOS
- iOS 中 UIView 和 CALayer 的關係iOSUIView
- iOS中copy和strong的個人理解iOS
- iOS中,Framework和 a的打包及使用iOSFramework
- iOS中 Debug 和 Release 的區別和使用iOS
- 聊聊iOS中的多繼承和多重代理iOS繼承
- css去除ios中input和textarea的陰影CSSiOS
- iOS 10 和macOS中的神經網路iOSMac神經網路
- OpenCV (iOS)中的腐蝕和膨脹(9)OpenCViOS
- iOS中的PromiseiOSPromise
- iOS:iOS8開發storyboard中autolayout和size class的使用詳解 (2)iOS
- iOS中assign和weak修飾符的區別iOS
- iOS中的StringiOS
- iOS 中 cell的用法iOS
- 聊聊iOS中的動畫iOS動畫
- iOS中的“鎖事”iOS
- IOS中的動畫使用iOS動畫
- iOS中RAC的使用iOS
- iOS中的動態庫,靜態庫和framework介紹iOSFramework
- vue中Axios的封裝和API介面的管理(更新)VueiOS封裝API
- iOS中觸控事件的傳遞和響應機制iOS事件
- 關於iOS中的執行緒安全和使用場景iOS執行緒
- SYS-BIOS中malloc和Memory_alloc的區別iOS
- iOS 中 各種 Cell 和 HeaderView 複用iOSHeaderView
- iOS Swift和OC專案中自定義LogiOSSwift
- iOS中擴充套件機制Category和associativeiOS套件Go
- iOS8中UIAlertView和UIActionSheet河裡去了?iOSUIView
- [譯] Story 中 Type Mode 在 iOS 和 Android 上的實現iOSAndroid
- iOS 中的事件傳遞和響應機制 - 原理篇iOS事件
- iOS 中的事件傳遞和響應機制 - 實踐篇iOS事件
- iOS 中的事件傳遞和響應機制 – 實踐篇iOS事件
- 關於 iOS 中的庫iOS
- iOS tableView中的MVC、MVVMiOSViewMVCMVVM
- iOS開發中的技巧iOS