iOS learning: isKindOfClass & isMemberOfClass

Basic knowledge

conclusion

  • +The isKindOfClass method starts from the isa point of the current class (that is, the metaclass of the current class), and searches along the superclass inheritance chain to determine and compare whether the classes are equal.
  • -The isKindOfClass object method starts from [self class] (the current class) and searches along the superclass inheritance chain to determine whether the class is equal to the comparison class.
  • +The isMemberOfClass method directly determines whether the isa point of the current class (that is, the metaclass of the current class) and the comparison class are equal.
  • -isMemberOfClass object method directly determines whether [self class] (current class) and comparison class are equal.

Basic knowledge

Object, class object and metaclass diagram:

Ex amp les & Analysis

// DZPerson inherits from 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. Can you find [NSObject class] --- > Yes on [NSObject class] [metaclass inheritance chain] 
        BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];     // 0 whether NSObject metaclass is equal to NSObject class -- > no
        BOOL re3 = [(id)[DZPerson class] isKindOfClass:[DZPerson class]];       // 0 can you find [DZPerson class] --- > no on [DZPerson class] [inheritance chain of metaclass]
        BOOL re4 = [(id)[DZPerson class] isMemberOfClass:[DZPerson class]];     // 0 whether DZPerson metaclass is equal to DZPerson class -- > no
        NSLog(@"\n re1:%hhd re2:%hhd re3:%hhd re4:%hhd",re1,re2,re3,re4);

        BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];       // 1. Can you find [nsobject class] --- > Yes on the [class inheritance chain] to which [NSObject alloc] belongs 
        BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];     // 1) whether the class to which the current [NSObject alloc] belongs is equal to the incoming [nsobject class] --- > Yes 
        BOOL re7 = [(id)[DZPerson alloc] isKindOfClass:[DZPerson class]];       // 1. Can you find [dzperson class] --- > Yes on the [inheritance chain of class] to which [DZPerson alloc] belongs 
        BOOL re8 = [(id)[DZPerson alloc] isMemberOfClass:[DZPerson class]];     // 1) whether the class to which the current [DZPerson alloc] belongs is equal to the incoming [nsobject class] --- > Yes 
        NSLog(@"\n re5:%hhd re6:%hhd re7:%hhd re8:%hhd",re5,re6,re7,re8);
    }
    return 0;
}

The above code actually calls four methods:

  1. Class method:
    1. +isKindOfClass
    2. +isMemberOfClass
  2. Object method:
    1. -isKindOfClass
    2. -isMemberOfClass

1. +isKindOfClass

+ (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);

    From the source code, we can see that self is the class itself, and object_getClass((id)self) is to obtain isa, which points to the metaclass, so tcls is actually the metaclass of the current class.

  • for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass)

    • The for loop actually starts from the metaclass of the current class and loops up along the superclass in the inheritance chain. In the marked part of the isa pointing diagram below, the parent class of the NSObject metaclass is NSObject. So in the second loop, the superclass of the NSObject metaclass is the NSObject itself.
    • However, the inheritance chain of DZPerson metaclass is DZPerson metaclass - > nsobject metaclass - > nsobject, so there will never be its own DZPerson on the inheritance chain of DZPerson metaclass.
    • Therefore [(id)[NSObject class] isKindOfClass:[NSObject class]] = YES, and [(id)[DZPerson class] isKindOfClass:[DZPerson class]] == NO.

2. +isMemberOfClass

+ (BOOL)isMemberOfClass:(Class)cls {   
    return object_getClass((id)self) == cls;
}
  • It can be seen from the source code that the code directly judges whether the metaclass of the current class is equal to the incoming class.
  • Therefore, in [(id)[NSObject class] isMemberOfClass:[NSObject class]] and [(id)[DZPerson class] isMemberOfClass:[DZPerson class]], NSObject metaclass is not equal to NSObject, and DZPerson metaclass is not equal to DZPerson. Naturally, the result is NO.

3. -isKindOfClass

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

As we can see, the initial value of the for loop of the object method becomes [self class], that is, the superclass inheritance chain is found from the current class.

So [(id)[NSObject alloc] isKindOfClass:[NSObject class]] and [(id)[DZPerson alloc] isKindOfClass:[DZPerson class]] are both YES.

4. -isMemberOfClass

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}
  • -The isMemberOfClass object method is simpler. It directly determines whether the current class and the incoming class are equal.
  • [(id)[NSObject alloc] isMemberOfClass:[NSObject class]] and [(id)[DZPerson alloc] isMemberOfClass:[DZPerson class]] are naturally YES.

isKindOfClass and isMemberOfClass in iOS

Tags: iOS objective-c

Posted by iifs044 on Tue, 06 Sep 2022 02:35:08 +0930