1. objc_getClass
通过类名来获取一个类对象,传入 const char *
返回对应的类对象。
- 源码
/***********************************************************************
* objc_getClass. Return the id of the named class. If the class does
* not exist, call _objc_classLoader and then objc_classHandler, either of
* which may create a new class.
* Warning: doesn't work if aClassName is the name of a posed-for class's isa!
**********************************************************************/
Class objc_getClass(const char *aClassName)
{
if (!aClassName) return Nil;
// NO unconnected, YES class handler
return look_up_class(aClassName, NO, YES);
}
示例:
Class c1 = objc_getClass((const char *)"NSObject");
Class c2 = objc_getClass((const char *)"NSObject"
Class c3 = [NSObject class];
NSObject *ojb = [[c1 alloc] init];
NSLog(@"%p, %p, %p", c1, c2 , c3 );
//0x7fff94d1c118, 0x7fff94d1c118, 0x7fff94d1c118
NSLog(@"%p", ojb );
//0x10071c950
2. class、supperClass
实例对象、类对象调用class
方法都返回类对象
- (Class)class {
//self->isa
return object_getClass(self);
}
/*
* objc_msgSendSuper 的消息接受者仍然是self,只是从父类开始查找方法的实现,class最终再NSObject中找到。调用者仍然是self。
* [super message]的底层实现
* 1.消息接收者仍然是子类对象
* 2.从父类开始查找方法的实现
* 最终调用的其实是 [self messges]
* 3. class方法最终再NSObject中找到,调用者仍然是self,所以[super class]仍然打印MJStudent
*/
- (Class)superclass
{
return class_getSuperclass(object_getClass(self));
}
+ (Class)class {
return self;
}
示例:
NSObject *object1 = [[NSObject alloc] init];
Class object2 = object_getClass(object1);
// 0x7fff94d1c118 0x7fff94d1c118 0x7fff94d1c118
NSLog(@"%p %p %p",[NSObject class], [object1 class], [object2 class]);
3. object_getClass
传入一个对象,获取该对象isa指针
指向的对象
。
- 源码
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
如果传入的是
实例对象instance
,则返回类对象class
,
如果传入的是类对象class
,则返回元类对象meta-class
,
如果传入的是元类对象meta-class
,则返回NSObject(基类)的元类对象meta-class
。
示例:
NSObject *instanceClass = [[NSObject alloc] init];
Class classObj = object_getClass(instanceClass);
Class metaclassObj = object_getClass(classObj);
NSLog(@"%p %p %p",instanceClass, classObj, metaclassObj);
//0x100743440 0x7fff94d1c118 0x7fff94d1c0f0
NSLog(@"%p ", [NSObject class]);//0x7fff94d1c118
bool isMeta = class_isMetaClass(metaclassObj);
NSLog(@"metaclassObj : %d ", isMeta);// 1
4 isKindOfClass 与 isMemberOfClass 区别
- 如果是实例对象
-isMemberOfClass:
表示该调用者是否是传入类的实例对象。
-isKindOfClass:
表示该调用者是否是传入类或其子类的实例对象。
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
- 如果是类对象
+isMemberOfClass:
表示该调用者isa指针所指对象 与 传入的对象是否一致。
+isKindOfClass:
表示该调用者isa指针所指对象 与 传入类或其子类是否一致。
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
5 实例分析
@interface LXPerson : NSObject
@end
@interface LXStudent : LXPerson
@end
分析以下结果:
@implementation LXStudent
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"%@",[self class]);
NSLog(@"%@",[self superclass]);
NSLog(@"%@",[super class]);
NSLog(@"%@",[super superclass]);
}
return self;
}
//LXStudent LXPerson LXStudent LXPerson
BOOL res11 = [[LXStudent new] isKindOfClass: [LXStudent class]];
BOOL res12 = [[LXStudent new] isMemberOfClass: [LXStudent class]];
BOOL res21 = [[LXStudent new] isKindOfClass: [NSObject class]];
BOOL res22 = [[LXStudent new] isMemberOfClass: [NSObject class]];
/* YES YES YES NO*/
BOOL res31 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL res32 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res33 = [[NSObject class] isMemberOfClass:object_getClass([NSObject class])];
/* YES NO YES*/
BOOL res41 = [[LXPerson class] isKindOfClass:[LXPerson class]];
BOOL res42 = [[LXPerson class] isKindOfClass:[NSObject class]];
BOOL res43 = [[LXPerson class] isKindOfClass:object_getClass([LXPerson class])];
/* NO YES YES*/
BOOL res44 = [[LXPerson class] isMemberOfClass:[LXPerson class]];
BOOL res45 = [[LXPerson class] isMemberOfClass:[NSObject class]];
BOOL res46 = [[LXPerson class] isMemberOfClass:object_getClass([LXPerson class])];
/* NO NO YES */