获取Class

作者: 学习路上一个远行者 | 来源:发表于2017-08-25 09:54 被阅读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

相关文章

  • android和iOS 通过className获取Class

    android获取class iOS获取class

  • 前端面试(二)

    一、jquery添加、删除class样式 1、使用attr()方法获取class和设置class 获取: 设置: ...

  • 反射

    获取类的Class对象 直接通过类.class,获取其Class对象 通过Class的forName方法 通过类实...

  • 获取Class

    Class class本质是一个结构体的指针,结构体是objc_class,这个结构体中包含了: isa (实例-...

  • 反射基础

    材料准备 Class类 获取Class对象通过类名.class获取通过对象名.getClass()获得通过Clas...

  • 02.Objective-C 对象的分类

    问题 Objective-C对象分类 整么获取到class对象,整么获取到meta-class对象 class对象...

  • Java中反射的简单使用

    1、获取Class对象 获取Class对象有三种方式,如下: 2、获取属性 3、获取构造方法 4、实利化对象 5、...

  • Scala 类型系统

    1.在scala泛型中获取其 Class[T] 需求:获取一个泛型 T 的 class 类型的 Class[T],...

  • 反射

    获取class的三种方式 1、根据对象获取 对象.getClass 2、根据类获取 类名.class 3、根据全类...

  • iOS获取属性具体类型类型

    Objective-C class类型:可以通过self.class获取 基础数据类型获取方式如下: Swift ...

网友评论

    本文标题:获取Class

    本文链接:https://www.haomeiwen.com/subject/ocrzrxtx.html