OC类的定义

作者: 熊妹妹 | 来源:发表于2016-11-08 19:39 被阅读527次

本文通过阅读runtime代码来分析NSObject。我们都知道NSObject是oc继承的跟类,提供一些通用的方法。从定义上看到NSObject满足NSObject协议,NSObject协议定义一些基础方法。

把NSObject.h用clang -rewrite-objc转成c++代码会发现NSObject的定义

#ifndef _REWRITER_typedef_NSObject
#define _REWRITER_typedef_NSObject
typedef struct objc_object NSObject;
typedef struct {} _objc_exc_NSObject;
#endif

struct NSObject_IMPL {
 Class isa;
};

发现NSObject是struct的别名,也就是说所有的类都是objc_object类型的结构体。NSObject的属性都存放在NSObject_IMPL这个结构体中。在编码中我们知道所有的类都可以赋值给id类型,这是为什么呢?在objc-private.h中可以找到id的定义:

typedef struct objc_class *Class;
typedef struct objc_object *id;

struct objc_object {
 ...
}

struct objc_class : objc_object {
 ...
}

Class是objc_class类型指针,id是objc_object类型的指针,所有的类也都是objc_object。

上面NSObject定义后面跟着一个NSObject_IMPL结构体,他存放着NSObject的变量。加一段测试代码。

@interface TestClass : NSObject

@property (nonatomic,assign) int i;

- (int)plus:(int)j;

@end

@implementation TestClass

- (int)plus:(int)j {
    return self.i+j;
}

转成c++代码后,声明的部分:

#ifndef _REWRITER_typedef_TestClass
#define _REWRITER_typedef_TestClass
typedef struct objc_object TestClass;
typedef struct {} _objc_exc_TestClass;
#endif

extern "C" unsigned long OBJC_IVAR_$_TestClass$_i;
struct TestClass_IMPL {
 struct NSObject_IMPL NSObject_IVARS;
 int _i;
};

TestClass同样被定义为objc_object的别名,这里并没有体现和NSObject的关系。但是在存放变量的TestClass_IMPL内体现了对NSOBject的继承关系,NSObject_IMPL作为了TestClass_IMPL的第一个数据。

static int _I_TestClass_i(TestClass * self, SEL _cmd) { return (*(int *)((char *)self + OBJC_IVAR_$_TestClass$_i)); }
static void _I_TestClass_setI_(TestClass * self, SEL _cmd, int i) { (*(int *)((char *)self + OBJC_IVAR_$_TestClass$_i)) = i; }

实现部分,默认生成了get和set两个静态方法,参数是对象和方法名。知道了变量是如何继承的,那类名是如何关联上的呢?在runtime初始化时会调用OBJC_CLASS_SETUP函数,进行类对象、元类对象中 isa、superclass 变量的设置。

static struct _class_ro_t _OBJC_METACLASS_RO_$_TestClass __attribute__ ((used, section ("__DATA,__objc_const"))) = {
 1, sizeof(struct _class_t), sizeof(struct _class_t), 
 (unsigned int)0, 
 0, 
 "TestClass",
 0, 
 0, 
 0, 
 0, 
 0, 
};

static struct _class_ro_t _OBJC_CLASS_RO_$_TestClass __attribute__ ((used, section ("__DATA,__objc_const"))) = {
 0, __OFFSETOFIVAR__(struct TestClass, _i), sizeof(struct TestClass_IMPL), 
 (unsigned int)0, 
 0, 
 "TestClass",
 (const struct _method_list_t *)&_OBJC_$_INSTANCE_METHODS_TestClass,
 0, 
 (const struct _ivar_list_t *)&_OBJC_$_INSTANCE_VARIABLES_TestClass,
 0, 
 (const struct _prop_list_t *)&_OBJC_$_PROP_LIST_TestClass,
};

extern "C" __declspec(dllimport) struct _class_t OBJC_METACLASS_$_NSObject;

extern "C" __declspec(dllexport) struct _class_t OBJC_METACLASS_$_TestClass __attribute__ ((used, section ("__DATA,__objc_data"))) = {
 0, // &OBJC_METACLASS_$_NSObject,
 0, // &OBJC_METACLASS_$_NSObject,
 0, // (void *)&_objc_empty_cache,
 0, // unused, was (void *)&_objc_empty_vtable,
 &_OBJC_METACLASS_RO_$_TestClass,
};

extern "C" __declspec(dllimport) struct _class_t OBJC_CLASS_$_NSObject;

extern "C" __declspec(dllexport) struct _class_t OBJC_CLASS_$_TestClass __attribute__ ((used, section ("__DATA,__objc_data"))) = {
 0, // &OBJC_METACLASS_$_TestClass,
 0, // &OBJC_CLASS_$_NSObject,
 0, // (void *)&_objc_empty_cache,
 0, // unused, was (void *)&_objc_empty_vtable,
 &_OBJC_CLASS_RO_$_TestClass,
};
static void OBJC_CLASS_SETUP_$_TestClass(void ) {
 OBJC_METACLASS_$_TestClass.isa = &OBJC_METACLASS_$_NSObject;
 OBJC_METACLASS_$_TestClass.superclass = &OBJC_METACLASS_$_NSObject;
 OBJC_METACLASS_$_TestClass.cache = &_objc_empty_cache;
 OBJC_CLASS_$_TestClass.isa = &OBJC_METACLASS_$_TestClass;
 OBJC_CLASS_$_TestClass.superclass = &OBJC_CLASS_$_NSObject;
 OBJC_CLASS_$_TestClass.cache = &_objc_empty_cache;
}
#pragma section(".objc_inithooks$B", long, read, write)
__declspec(allocate(".objc_inithooks$B")) static void *OBJC_CLASS_SETUP[] = {
 (void *)&OBJC_CLASS_SETUP_$_TestClass,
};

OBJC_CLASS_$_TestClassOBJC_METACLASS_$_TestClass都是_class_t类型,其中的class_ro_t中包含了类名(name)、method_list_t(方法列表)、protocol_list_t(协议列表)、ivar_list_t(实例变量列表)、property_list_t(属性列表)等信息。

struct _class_t {
 struct _class_t *isa;
 struct _class_t *superclass;
 void *cache;
 void *vtable;
 struct _class_ro_t *ro;
};
struct _class_ro_t {
 unsigned int flags;
 unsigned int instanceStart;
 unsigned int instanceSize;
 unsigned int reserved;
 const unsigned char *ivarLayout;
 const char *name;
 const struct _method_list_t *baseMethods;
 const struct _objc_protocol_list *baseProtocols;
 const struct _ivar_list_t *ivars;
 const unsigned char *weakIvarLayout;
 const struct _prop_list_t *properties;
};

类会生成一个名为OBJC_CLASS_$_TestClass的_class_t类型结构体来存储它的一些信息。所以类都会生成对应的结构体变量,它的isa指向它的元类结构体变量(_class_t同类型),supperclass指向它继承类的结构体变量。实例方法定义在类中,类方法定义在元类中。元类的isa和supperclass指向继承类的元类结构体变量。
最后OBJC_CLASS_$_TestClass还会存放到L_OBJC_LABEL_CLASS_$数组中。

static struct _class_t *L_OBJC_LABEL_CLASS_$ [1] __attribute__((used, section ("__DATA, __objc_classlist,regular,no_dead_strip")))= {
 &OBJC_CLASS_$_TestClass,
};

相关文章

  • From Objective-C to Ruby(4)-类和模块

    类 定义类 OC: ruby: 初始化方法 OC: ruby: 实例变量和属性 OC: ruby: 类方法和对象方...

  • swift方法

    oc中只有类可以定义方法,swift类/结构体/枚举都能定义方法 swift的类型方法类似oc的类方法 实例方法(...

  • OC:类的定义

    目录 如何定义类 我们都知道Objective-C起源于C语言,C是面向过程的语言,Objective-C是面向对...

  • OC类的定义

    本文通过阅读runtime代码来分析NSObject。我们都知道NSObject是oc继承的跟类,提供一些通用的方...

  • Swift 和 OC 混编踩坑指南

    Subclass 对于自定义的类而言,OC 的类,不能继承自 Swift 的类,即要混编的 OC 类不能是 Swi...

  • Swift报错:fatal error: use of unim

    OC与Swift混编时,创建一个swift类继承自OC类,由于这个OC类已自定义构造函数,所以在这个swift类中...

  • Swift中使用KVC遇到的问题

    OC中使用KVC是因为NSObject遵循了NSKeyValueCoding协议,而OC中所有的类包括自定义类的根...

  • OC底层-类和对象

    类和对象 OC中的类 OC中.类基于C/C++的结构体. 通过查看NSObject的类定义,可以看到内部有一个Cl...

  • Swift-OC互相调用注意事项

    1、swift调用OC的方法,如果OC方法参数是自定义的类,同时需要把自定义的类导入到桥文件中,否则无法调用。 2...

  • iOS/macOS - Customize the NSAppl

    -- OC项目中自定义 application 类 macOS Step 1: 创建自己的类:CustomAppl...

网友评论

    本文标题:OC类的定义

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