共计 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;
}
总结:
-
object_getClass(obj)
返回的是 obj 的 isa 指针;
-
[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
余下剖析同理 ……