美文网首页
聊聊Objective-C的中的对象

聊聊Objective-C的中的对象

作者: 傻傻木 | 来源:发表于2018-05-13 17:29 被阅读0次

Objective-C中其实有三种对象,分别为实例对象(instance)、类对象(class)、元类对象(meta-class);那这三种对象有什么关系呢?以及三种对象本身存储了哪些信息呢?这是我们本文要探讨的问题。

我们知道Objective-C的类可以通过clang编译器转换为C++的结构体,也就是说,Objective-C对象的本质就是结构体,下面通过实践来证明。

  • 创建一个命令行项目(这里可以找到),在main.m文件添加如下的代码
#import <Foundation/Foundation.h>
@interface Person: NSObject {
    int _age;
    double _height;
}
@end

@implementation Person
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
    }
    return 0;
}

然后使用clang编译器重写main.m文件,可指定平台iOS和架构arm64,在main.m所在的文件夹执行如下命令
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
会得到一个main-arm64.cpp的文件,可看到Person类转换为struct Person_IMPL结构体

struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _age;
    double _height;
};

存在上面定义Person类时声明的_age_height成员变量,发现第一个成员变量是struct NSObject_IMPL结构体,这是NSObjectclang编译器重写后对应的结构体,在main-arm64.cpp文件中可找到声明

struct NSObject_IMPL {
    Class isa;
};

实例对象(instance)

Objictive-C实例对象是通过类对象创建

Person *p1 = [Person new];
Person *p2 = [[Person alloc] init];

实例对象分配在堆空间,所以p1、p2指向的内存地址都在上;每次创建的都是不同的对象,所以在内存中会存在很多个实例对象。

struct NSObject_IMPLstruct Person_IMPL合并一下得到下面的结构

struct Person_IMPL {
    Class isa;
    int _age;
    double _height;
};

这也是Person实例对象在内存中的布局情况。

总结一下实例对象中包含信息

  • isa指针,指向类对象
  • 成员变量
    其实isa也是成员变量,只不过比较特殊,它指向这个实例对象的类对象。

类对象(class)

类对象是对实例对象的描述,描述这个类实例对象有哪些成员变量、属性、对象方法、类方法,那这些信息存储在什么地方呢?(下面提及的数据类型这里可以找到)

类对象声明为typedef struct objc_class *Class;,再看看struct objc_class结构体,截取一些关键的信息看看

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    class_rw_t *data() { 
        return bits.data();
    }
    // ... 还有很多方法,略去
};

superclass指向父类,其他的信息存储在class_rw_t的结构体中,定义如下

struct class_rw_t {
    const class_ro_t *ro; // 实例变量信息
    method_array_t methods; // 对象方法信息
    property_array_t properties; // 属性信息
    protocol_array_t protocols; // 协议信息
     // ... 省略其他信息
}

runtime提供这些信息函数如下

获取实例变量

Ivar *
class_copyIvarList(Class cls, unsigned int *outCount)

获取属性信息

objc_property_t * 
class_copyPropertyList(Class cls, unsigned int *outCount)

获取对象方法

// 第一个参数是 *类对象*,返回的是*对象方法*;如果是参数*元类对象*,返回的是*对象方法*
Method *
class_copyMethodList(Class cls, unsigned int *outCount)

获取协议信息

Protocol * __unsafe_unretained * 
class_copyProtocolList(Class cls, unsigned int *outCount)

struct objc_class继承objc_objectstruct objc_object结构如下

struct objc_object {
private:
    isa_t isa;
    // ...省略方法
}

isa_t是联合体,结构如下

union isa_t 
{
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }
    Class cls;
    uintptr_t bits;
     // ...省略
}

这里面有个 cls成员,这个就是class指向mata-class的指针。

总结一下类对象(class)中存储的信息

  • isa指针,指向元类的指针
  • superclass指向父类的指针
  • 成员变量(Ivar)的描述信息
  • 属性(property)的描述信息
  • 对象方法(Instance Method)的描述信息
  • 遵循协议(protocol)的描述信息

元类对象(meta-class)

上面可以看出,meta-class也是一个Class 类型,与类对象的数据类型时一样的,只不过存储的信息不同。
元类对象(meta-class)存储的信息有

  • isa指针,指向基类(NSObject)元类(meta-class)的指针,所有元类(meta-class)isa指针都指向NSObject元类的指针。
  • superclass指向父类的元类(meta-class)的指针
  • 类方法(class Method)的描述信息

总结

上面讲了实例对象的内存布局,以及实例对象(instance)类对象(class)元类对象(meta-class)之间的关系,最后用一张图来说明它们之间的关系。

class-inherit.png

参考文章

详解Objective-C的isa与meta-class
Objective-C 中的 Meta-class 是什么?

相关文章

  • 聊聊Objective-C的中的对象

    Objective-C中其实有三种对象,分别为实例对象(instance)、类对象(class)、元类对象(met...

  • Objective-C对象的分类

    一、Objective-C对象的分类 Objective-C中的对象,简称OC对象,主要可以分为3种 instan...

  • OC对象的分类

    Objective-C对象的分类 Objective-C中的对象也叫OC对象,主要分为三类:1.实例对象(inst...

  • 第六条: 理解“属性”这一概念

    "属性"(property)是Objective-C的一项特性,用于封装对象中的数据。Objective-C对象通...

  • Objective-C的底层实现(类与对象)

    概述 对象 Objective-C中,类和对象的底层数据结构,可以参考Objective-C底层数据结构。其中对象...

  • Objective-C中的对象

    Objective-C中的对象大致可以分为:instance对象、class对象、metaclass对象。建议下载...

  • OC 对象的分类

    Objective-C中的对象,简称OC对象,主要可以分为3种 instance对象(实例对象) class对象(...

  • iOS底层 -- OC对象的分类

    Objective-C中的对象,简称OC对象,主要可以分为3种 instance对象(实例对象) class对象(...

  • OC对象的本质及底层探究

    Objective-C中的对象,简称OC对象,主要分为3种: instance对象(实例对象) class对象(类...

  • 01 - OC对象的分类

    我们知道Objective-C是面向对象的一门语言,那么Objective-C中的对象,可以分为3种 instan...

网友评论

      本文标题:聊聊Objective-C的中的对象

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