<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                [toc] 開發中經常會使用 `isKindOfClass` 判斷對象是否是某個類或者是其父類(整個繼承鏈上的類),很少會用到 `isMemberOfClass` ,本文就從源碼層面來探索他們之間的關系。 ## 一、準備 ```objectivec // DZPerson繼承自NSObject @interface DZPerson : NSObject @end #import <Foundation/Foundation.h> #import "DZPerson.h" #import <objc/runtime.h> int main(int argc, const char * argv[]) { @autoreleasepool { BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; // 1 BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; // 0 BOOL re3 = [(id)[DZPerson class] isKindOfClass:[DZPerson class]]; // 0 BOOL re4 = [(id)[DZPerson class] isMemberOfClass:[DZPerson class]]; // 0 NSLog(@"\n re1:%hhd re2:%hhd re3:%hhd re4:%hhd",re1,re2,re3,re4); BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; // 1 BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; // 1 BOOL re7 = [(id)[DZPerson alloc] isKindOfClass:[DZPerson class]]; // 1 BOOL re8 = [(id)[DZPerson alloc] isMemberOfClass:[DZPerson class]]; // 1 NSLog(@"\n re5:%hhd re6:%hhd re7:%hhd re8:%hhd",re5,re6,re7,re8); } return 0; } /** 打印: re1:1 re2:0 re3:0 re4:0 re5:1 re6:1 re7:1 re8:1 */ ``` ## 二、源碼分析 上述代碼其實調用了四個方法: >類方法: +isKindOfClass +isMemberOfClass >對象方法: -isKindOfClass -isMemberOfClass ### 1. +isKindOfClass 源碼 ```objectivec + (BOOL)isKindOfClass:(Class)cls { for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) { if (tcls == cls) return YES; } return NO; } Class object_getClass(id obj) { if (obj) return obj->getIsa(); else return Nil; } ``` - **Class tcls = object_getClass((id)self);** 從源碼可以看到,`self` 是類本身,`object_getClass((id)self)` 則是獲取 `isa`,而 `isa` 是指向`元類`的,所以 `tcls` 實際上是當前類的元類。 - **for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass)** - for循環實際上就是從`當前類的元類`開始,沿著繼承鏈中的 `superclass` 一直向上循環,在如下 `isa`指向圖 中標注部分,`NSObject`元類 的父類是 `NSObject`。所以在第二次循環的時候,`NSObject`元類 的 `superclass` 是本身`NSObject`。 - 但是 `DZPerson`元類 的繼承鏈是`DZPerson元類 -> NSObject元類 -> NSObject`,所以在 `DZPerson`元類 的繼承鏈上永遠不會有自身`DZPerson`。 - 因此 `[(id)[NSObject class] isKindOfClass:[NSObject class]] = YES` ,而 `[(id)[DZPerson class] isKindOfClass:[DZPerson class]] == NO`。 ![](https://img.kancloud.cn/73/67/736752e0e4d381e892f08b1d0a359dcf_1200x520.png) ### 2. +isMemberOfClass 源碼 ```objectivec + (BOOL)isMemberOfClass:(Class)cls { return object_getClass((id)self) == cls; } ``` - 從源碼中可以看到,代碼是直接判斷當前`類的元類`是否等于傳入類。 - 所以 `[(id)[NSObject class] isMemberOfClass:[NSObject class]]` 和 `[(id)[DZPerson class] isMemberOfClass:[DZPerson class]]`中,`NSObject`元類 不等于 `NSObject`,`DZPerson`元類 也不等于 `DZPerson`,結果自然都是 `NO`。 ### 3. -isKindOfClass 源碼 ```objectivec - (BOOL)isKindOfClass:(Class)cls { for (Class tcls = [self class]; tcls; tcls = tcls->superclass) { if (tcls == cls) return YES; } return NO; } ``` 我們可以看到,對象方法的 for循環 初始值 變成了 [self class],也就是從當前類開始找superclass繼承鏈。 所以 [(id)[NSObject alloc] isKindOfClass:[NSObject class]] 和 [(id)[DZPerson alloc] isKindOfClass:[DZPerson class]] 都為 YES。 ### 4. -isMemberOfClass 源碼 ```objectivec - (BOOL)isMemberOfClass:(Class)cls { return [self class] == cls; } ``` - `-isMemberOfClass` 對象方法更是簡單了,直接就是判斷`當前類`和傳入類是否相等。 - `[(id)[NSObject alloc] isMemberOfClass:[NSObject class]]` 和 `[(id)[DZPerson alloc] isMemberOfClass:[DZPerson class]]` 自然都是 `YES`。 ## 三、總結 - `+isKindOfClass` 類方法是從`當前類的isa指向` (也就是當前類的元類) 開始,沿著 `superclass` 繼承鏈查找判斷和對比類是否相等。 - `-isKindOfClass` 對象方法是從 `[self class]` (當前類) 開始,沿著 `superclass` 繼承鏈查找判斷和對比類是否相等。 - `+isMemberOfClass` 類方法是直接判斷當前`類的isa指向` (也就是當前類的元類) 和對比類是否相等。 - `-isMemberOfClass` 對象方法是直接判斷 `[self class]` (當前類) 和對比類是否相等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看