iOS 与前端程序猿阵线联盟-汇总各类技术干货iOS Developer

获取Class

2017-08-25  本文已影响25人  学习路上一个远行者

Class

class本质是一个结构体的指针,结构体是objc_class,这个结构体中包含了:

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

上一篇下一篇

猜你喜欢

热点阅读