关于ios:iOS笔记-10isKindOfClass与isMemberOfClass

41次阅读

共计 4534 个字符,预计需要花费 12 分钟才能阅读完成。

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] class] isKindOfClass:(id)[NSObject class]];

// true
BOOL res6 = [(id)[[NSObject new] class] 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. 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]的 isa 是 NSObjectMeta,即 NSObject != NSObjectMeta,即 NSObject,所以是 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

余下剖析同理 ……

正文完
 0