iOS笔记系列目录

一 Code


- (void)testClassISA {

id b1 = [NSObject class];

id b2 = [NSObject class];

id b3 = [[NSObject new] class];

NSLog(@"[NSObject class] = %@ , %@, %@", b1,b2,b3);

// true
BOOL res1 = [(id)[NSObject class] isKindOfClass:(id)[NSObject class]];

// false
BOOL res2 = [(id)[NSObject class] isMemberOfClass:(id)[NSObject class]];

// true
BOOL res3 = [(id)[[NSObject new] class] isKindOfClass:(id)[NSObject class]];

// false
BOOL res4 = [(id)[[NSObject new] class] isMemberOfClass:(id)[NSObject class]];

// true
BOOL res5 = [(id)[NSObject new] isKindOfClass:(id)[NSObject class]];

// true
BOOL res6 = [(id)[NSObject new] isMemberOfClass:(id)[NSObject class]];

// false
BOOL res7 = [(id)[Test class] isKindOfClass:(id)[Test class]];

// false
BOOL res8 = [(id)[Test class] isKindOfClass:(id)[Test class]];

// false
BOOL res9 = [(id)[[Test new] class] isKindOfClass:(id)[Test class]];

// false
BOOL res10 = [(id)[[Test new] class] isMemberOfClass:(id)[Test class]];

// true
BOOL res11 = [(id)[Test new] isKindOfClass:(id)[Test class]];

// true
BOOL res12 = [(id)[Test new] isMemberOfClass:(id)[Test class]];

// 1, 0, 1, 0, 1, 1
NSLog(@"%d, %d, %d, %d, %d, %d",res1, res2, res3,res4,res5, res6);

// 0, 0, 0, 0, 1, 1
NSLog(@"%d, %d, %d, %d, %d, %d",res7, res8, res9,res10,res11, res12);

}

二 源码

0.源码解析


/// 类方法,返回自身

+ (Class)class {

return self;

}

/// 实例方法,查找isa(类)

- (Class)class {

return object_getClass(self);

}

Class object_getClass(id obj)

{

if (obj) return obj->getIsa();

else return Nil;

}

inline Class

objc_object::getIsa()

{

if (isTaggedPointer()) {

uintptr_t slot = ((uintptr_t)this >> TAG_SLOT_SHIFT) & TAG_SLOT_MASK;

return objc_tag_classes[slot];

}

return ISA();

}

inline Class

objc_object::ISA()

{

assert(!isTaggedPointer());

return (Class)(isa.bits & ISA_MASK);

}

/// 类方法,沿着继承链,去判定isa(类对象isa是元类)和参数是否相等

+ (BOOL)isKindOfClass:(Class)cls {

for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {

if (tcls == cls) return YES;

}

return NO;

}

/// 实例方法,沿着继承链,去判定isa(实例对象isa是类)和参数是否相等

- (BOOL)isKindOfClass:(Class)cls {

for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {

if (tcls == cls) return YES;

}

return NO;

}

/// 类方法,判定isa(元类)和参数是否相等

+ (BOOL)isMemberOfClass:(Class)cls {

return self->ISA() == cls;

}

/// 实例方法,判定isa(类)和参数是否相等

- (BOOL)isMemberOfClass:(Class)cls {

return [self class] == cls;

}

总结:

    1. object_getClass(obj)返回的是obj的isa指针;
    1. [obj class]则分两种情况:
  • obj为实例对象

调用的是实例方法:- (Class)class,返回的obj对象中的isa指针;

  • obj为类对象(包括元类和根类以及根元类)

调用的是类方法:+ (Class)class,返回的结果为其本身。

参考:【iOS笔记 #3】class方法和objc_getClass方法

1.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.

判定依据

实例对象调用isKindOfClass

沿继承链获取isa(类对象),判定class与继承链上获取的isa是否有相等的

类对象调用isKindOfClass

沿继承链获取isa(元类对象),判定class与继承链上获取的isa是否有相等的

2.isMemberOfClass

是否是给定类的实例

Returns a Boolean value that indicates whether the receiver is an instance of a given class.

isMemberOfClass的源码实现是拿到自己的isa指针和自己比较,是否相等。

图1

三 解析

1. res1


BOOL res1 = [(id)[NSObject class] isKindOfClass:(id)[NSObject class]]; // true

[NSObject class]类对象调用+(Class)class返回自身,即NSObject


/// 类方法,沿着继承链,去判定isa(类对象isa是元类)和参数是否相等

+ (BOOL)isKindOfClass:(Class)cls;

返回自身,即NSObject的isa是NSObjectMeta,不等,沿继承链查找superclass,[NSObjectMeta superclass] == NSObject(图右上角可看出),此时相等,返回true

2. res2


BOOL res2 = [(id)[NSObject class] isMemberOfClass:(id)[NSObject class]]; // false

[NSObject class]即NSObject


/// 类方法,判定isa(元类)和参数是否相等

+ (BOOL)isMemberOfClass:(Class)cls;

[NSObject class] == NSObject,[NSObject class]的isa是NSObjectMeta,NSObject != NSObjectMeta,所以是false

3. res3


BOOL res3 = [(id)[[NSObject new] class] isKindOfClass:(id)[NSObject class]]; // true

[NSObject new] class] == NSObject,后续分析与res1一致,所以是true

4. res4


BOOL res4 = [(id)[[NSObject new] class] isMemberOfClass:(id)[NSObject class]]; // false

[NSObject new] class] == NSObject,后续分析与res2一致,所以是false

5. res5


BOOL res5 = [(id)[NSObject new] isKindOfClass:(id)[NSObject class]]; // true

/// 实例方法,沿着继承链,去判定isa(实例对象isa是类)和参数是否相等

- (BOOL)isKindOfClass:(Class)cls;

id o = [NSObject new]; o 的calss是NSObject,[NSObject class] == NSObject,进入循环即相等,所以是true

6. res6


BOOL res6 = [(id)[NSObject new] isMemberOfClass:(id)[NSObject class]]; // true

/// 实例方法,判定isa(类)和参数是否相等

- (BOOL)isMemberOfClass:(Class)cls;

id o = [NSObject new]; o 的isa是NSObject,[NSObject class] == NSObject,进入循环即相等,所以是true

7. res7


BOOL res7 = [(id)[Test class] isKindOfClass:(id)[Test class]]; // false

[Test class] == Test


/// 类方法,沿着继承链,去判定isa(类对象isa是元类)和参数是否相等

+ (BOOL)isKindOfClass:(Class)cls;

1 -> Test的isa是TestMeta,TestMeta != Test;

2 -> 找superclass,[Test superclass] == NSObject,NSObject的isa是NSObjectMeta,NSObjectMeta != Test;

3 -> 继续找superclass,[NSObject superclass] == nil,nil != Test,所以是false

8. res8


BOOL res8 = [(id)[[Test new] class] isKindOfClass:(id)[Test class]]; // false

[Test class] == Test,[Test new] class] == Test


/// 类方法,沿着继承链,去判定isa(类对象isa是元类)和参数是否相等

+ (BOOL)isKindOfClass:(Class)cls;

1 -> Test 的isa是TestMeta,不等于Test,

2 -> Test的superclass是NSObject,NSObject的isa是NSObjectMeat,不等于Test,

3 -> NSObject的superclass是nil,不等于Test,所以是false

余下分析同理......


总结一下判定流程
结合上图1,共有三列,第一列实例对象,第二列类对象,第三列元类对象。

  • + (BOOL)isKindOfClass:(Class)cls;
    类方法,沿着继承链,去判定isa(类对象isa是元类)和参数是否相等,即判定第三列的所有元类以及根元类的父类NSObject是否有能和参数匹配的。

参见res7的判定流程

  • - (BOOL)isKindOfClass:(Class)cls;
    实例方法,沿着继承链,去判定isa(实例对象isa是类)和参数是否相等,即判定第二列的所有类以及根类NSObject是否有能和参数匹配的。

参见res5的判定流程

  • + (BOOL)isMemberOfClass:(Class)cls;
    类方法,判定isa(元类)和参数是否相等,只判定一次,判定元类,即第三列是否有能和参数匹配的。

参见res2的判定流程

  • - (BOOL)isMemberOfClass:(Class)cls;
    实例方法,判定isa(类)和参数是否相等,只判定一次,判定元类,即第二列是否有能和参数匹配的。

参见res6的判定流程


Adrenine
9 声望3 粉丝

最怕一生碌碌无为却道平凡难能可贵!