We often use isKindOfClass in development to determine if an obJ is of a type. All of our knowledge is based on “class” ISA

isKindOfClass:

Looking at the objC4 source code, we can see that whoever calls isKindOfClass: will enter the objc_opt_isKindOfClass C function.

This C function is located in the nsobject. mm file

// Calls [obj isKindOfClass]
// objc_opt_isKindOfClass is raised when obj calls isKindOfClass
// obj is an id type. Id is a pointer to the objc_Object structure, meaning that the object passed in can be a time class or an instance object of the class
// otherClass is the isKindOfClass argument, which we passed in CLS
BOOL objc_opt_isKindOfClass(id obj, Class otherClass)
{
#if __OBJC2__
    if(slowpath(! obj))return NO;
    
    Class cls = obj->getIsa();	 // CLS here is only the first ISA of obj
    if(fastpath(! cls->hasCustomCore())) {// otherClass starts with obj's ISA and compares it with ISA's parent until it finds or its parent is nil
		// When the parent class is nil means that the last class to compare to otherClass is the NSObject root class.
        for (Class tcls = cls; tcls; tcls = tcls->superclass) {
            if (tcls == otherClass) return YES;
        }
        return NO;
    }
#endif
    return ((BOOL(*) (id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}
Copy the code

Get a message:

  • Everything starts with the isa of the caller OBj, and then goes down the superclass path until CLS or Superclass is nil is found
  • When superclass is nil, which means that the last root class NSObject is also not CLS, flase is returned.

On the basis of isa bitmap, the comparative judgment path of CLS in different situations is analyzed:

whenclassCall + (BOOL) isKinsOfClass CLS: (Class)

Represented by isa bitmap, the blue part is the link that CLS compares in sequence.

If it isClass object ttf_subclassCall isKindOfClass

Text Description:

  • Start with the ISA metaclass of the class. It’s not CLS
    • If so, return true
  • If not, continue to compare the metaclass superclass to CLS to see if it is CLS
  • Until the root class NSObject is done

SubClass ->MetaClass-> MetaClass->… ->RootMetaClass->NSObject

The essence of the method called by the class object is to determine whether the CLS is any member of the metaclass’s inheritance chain

If it isThe MetaClass MetaClassCall isKindOfClass

Again, the MetaClass ISA points to RootMetaClass, so start with RootMetaClass and compare to see if it’s the CLS we passed in, and if it’s not, then see if it’s the root class NSObject, and if NSObject isn’t either, it’s gone completely, Returns false,

CLS judgment order: MetaClass ->RootMetaClass->NSObject 

whenThe object objCall – (BOOL) isKinsOfClass CLS: (Class)

Start with the class object that isa points to and determine whether it is CLS. If not, look at the parent of the class object and determine whether it is CLS level by level. Return true until found, or if NSObject is still not found, return false.

The CLS judgment sequence is shown in the figure: Object ->SubClass -> SubClass ->... ->NSObject 

The essence is to determine whether CLS is any member of the class inheritance chain

isMemberofClass

whenclassCall + (BOOL) CLSS isMemberofClass: (Class)

+ (BOOL)isMemberOfClass:(Class) CLS source code

+ (BOOL)isMemberOfClass:(Class)cls {
    return self->ISA() == cls;
}
Copy the code

Instead of doing an isKindOfClass loop until it finds or nil, it just compares CLS to see if my current ISA points to, which returns true, not false.

This method is simply used to determine whether CLS is the caller’s ISA.

If it isClass object ttf_subclassCall isMemberofClass: Any class object passed is false

Because the isa of a class does not point to a class object, see the following figure

If it isThe MetaClass MetaClassCall isMemberofClass: Any class object passed is also false

  1. The reason as above 
  2. The ISA of the metaclass refers only to the root metaclass NSObejct 

whenThe object objCall – (BOOL) CLSS isMemberofClass: (Class)

– (BOOL)isMemberOfClass:(Class) CLS

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}
- (Class)class {
    return object_getClass(self); // Get the class to which the current ISA points
}

Copy the code

Just determine if the object’s ISA, the SubClass in the diagram, is the CLS we passed in

  1. Only determine if its class object is an incoming CLS 
  2. Only class objects are accepted, since there is no ISA, there is no metaclass intervention

Test case validation output:

Conclusion:

When the caller is —Class object ttf_subclass

+(BOOL)isKindOfClass:(Class)cls :

  • Check whether CLS is a metaclass -> parent metaclass -> parent metaclass ->… -> root metaclass ->NSObject (superclass inheritance chain of metaclass) one of them.
  • clsPass false to any class object except nsobject. class.

+ (BOOL) isMemeberOfClass CLS: (Class) :

  • To determine if CLS is your OWN ISA,

When the caller is —The MetaClass MetaClass

IsKindOfClass: (Class) + (BOOL) CLS:

  • Determine if CLS is any of the root metaclass ->NSObject

+ (BOOL) isMemeberOfClass CLS: (Class) :

  • Determine whether CLS is the root metaclass

When the caller is —The object Obj:

CLS – (BOOL) isKindOfClass: (Class) :

  • CLS = > CLS = > CLS = > CLS = > CLS ->NSObject ** (Superclass inheritance chain) one of them

CLS – (BOOL) isMemeberOfClass: (Class) :

  • judgeclsIs it your own?Class (Class object)