获取Class
2017-08-25 本文已影响25人
学习路上一个远行者
Class
class本质是一个结构体的指针,结构体是objc_class
,这个结构体中包含了:
- isa (实例->类->meta 类->root meta 类)root meta类指向本身
- 父类型的指针
- 类的名字
- 方法列表(可以是实例方法列表,也可以是类方法列表)
- 实现的协议列表
- 版本
- 保留的信息
id
id 本质也是一个结构体的指针,结构体是objc_object
这个结构体中包含:
struct objc_object { Class isa OBJC_ISA_AVAILABILITY; }
两个获取class的方法:
+(Class)class
这是一个类方法,源码是:
+ (Class)class { return self; }
类方法的class
是指向的自己本身,也许你在别人的代码中看见这样的一方法:
+(void)log {
[self.class logName];
// [self logName]; 他们是一个意思
}
这样当我们需要从一个类的实例对象来获取isa链,那么我们不应该通过这个类方法来获取。
NSObject *objc = [NSObject new];
[objc class]; // class
[[objc class] class]; // meta class
[[[objc class] class] class]; // root meta class
你的本意是上面的意思,但是这个错误的其实这段代码的含义是这样的:
NSObject *objc = [NSObject new];
[objc class]; // class
[[objc class] class]; // class
[[[objc class] class] class]; // class
因为类方法
+(Class)class
返回的是self
-(Class)class
实例方法,源码是:
- (Class)class { return object_getClass(self); }
我们从这个实例方法中我们可以看出来其实调用的是object_getClass(id)
那么这个方法的源码是什么呢?请看下一个章节
object_getClass
源码:
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
至于obj_getIsa()
这个方法是其实是获取就是获取Class结构体中isa所指向的class指针。你可以通过看源码来了解obj_getIsa()
的具体实现,源码
我们可以通过
Class object_getClass(id obj)
来获取isa链条
NSObject *objc = [NSObject new];
object_getClass(objc); // class
object_getClass(object_getClass(objc)); // meta class
object_getClass(object_getClass(object_getClass(objc))); //root meta class
我的问题
其实前面的知识,只是我通过看别的博客和简书得知,这里也就是做个记录,现在我要记录一下我疑惑的地方,并且通过做了验证的:
{
Class personClass = [Person class];
NSLog(@"Class------%p", personClass);
[self logPropertyAndIvarWithClass:personClass];
Person *person = [Person new];
Class class = person.class;
NSLog(@"Object------%p", class);
[self logPropertyAndIvarWithClass:class];
// 通过实例方法的-(Class)class 和类方法+(Class)class他们指向都是同一个指针,我们知道类在程序中也是一个对象,他们是一个单利。
}
- (void)logPropertyAndIvarWithClass:(Class)class {
unsigned int ivarCount = 0;
Ivar *ivars = class_copyIvarList(class, &ivarCount);
for (int i = 0 ; i < ivarCount; i++) {
Ivar ivar = ivars[i];
NSLog(@"ivar -- %@", [NSString stringWithUTF8String:ivar_getName(ivar)]);
}
unsigned int propertyCount = 0;
objc_property_t *properties = class_copyPropertyList(class, &propertyCount);
for (int i = 0 ; i < propertyCount; i++) {
objc_property_t property = properties[i];
NSLog(@"property -- %@", [NSString stringWithUTF8String:property_getName(property)]);
}
}
// 通过上面的两个方法中,我知道ivar 要比property的数量多。
注意:根据runtime获取出来的property,只能是自己本类的property,而不能打印出 继承父类 的property