您的位置:首页 > 移动开发 > Objective-C

objective c下的对象模型

2015-12-30 16:55 218 查看

前言

通过clang将objective c代码翻译成cpp代码,阅读代码的实现去理解objc中对象模型。

objective c代码

#import <Foundation/Foundation.h>

@interface TestA : NSObject {
int age;
NSString *name;
}
- (void)instanceMethod;
+ (void)classMethod;
@end

@implementation TestA
- (void)instanceMethod {
NSLog(@"instance method~");
}
+ (void)classMethod {
NSLog(@"class method~");
}
@end


代码块中含有类方法以及普通的方法。

clang翻译objective c代码块

clang -rewrite-objc TestA.m


Objective c的对象模型

先介绍一下objective c runtime下id以及class类型。

struct objc_class {
struct objc_class *isa;
.....
};
struct objc_object {
struct objc_class *isa;
};

typedef struct objc_class *Class; //类  (class object)
typedef struct objc_object *id;   //对象 (instance of class)


struct objc_object * id代表一个class instance的对象,在objc_object结构体中有一个成员isa,这个变量指向id对象所属class。

struct objc_class *Class代表一个类对象,在objc_class结构体中有一个成员isa,这个变量指向类对象的meta-class。

注意这两个结构体中的isa指向的内容是不同的。

通过clang的命令,已经将TestA.m文件翻译成TestA.cpp代码。

struct _class_t OBJC_CLASS_$_TestA __attribute__ ((used, section ("__DATA,__objc_data"))) = {
0, // &OBJC_METACLASS_$_TestA,
0, // &OBJC_CLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_CLASS_RO_$_TestA,
};

static struct _class_ro_t _OBJC_CLASS_RO_$_TestA __attribute__ ((used, section ("__DATA,__objc_const"))) = {
0, __OFFSETOFIVAR__(struct TestA, age), sizeof(struct TestA_IMPL),
(unsigned int)0,
0,
"TestA",
(const struct _method_list_t *)&_OBJC_$_INSTANCE_METHODS_TestA,
0,
(const struct _ivar_list_t *)&_OBJC_$_INSTANCE_VARIABLES_TestA,
0,
0,
};


这里 struct class_t OBJC_CLASS$_TestA 对应的就是前面介绍的 struct objc_class 结构体,我们可以观察struct objc_class 结构体中包含的信息。这里我们转译一下此结构体方便阅读。

struct objc_class {
Class isa;
Class super_class                                        OBJC2_UNAVAILABLE;
const char *name                                         OBJC2_UNAVAILABLE;
long version                                             OBJC2_UNAVAILABLE;
long info                                                OBJC2_UNAVAILABLE;
long instance_size                                       OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
} ;


对比上下两个结构体,可以看出整个struct objc_class所包含的信息。

这里主要介绍几个重要的信息。

变量含义
isaclass的meta-class, TestA metaclass是OBJC_METACLASS_$_TestA
super_classclass的superclass, TestA superclass是OBJC_CLASS_$_NSObject
const char *name类名, 在结构体中OBJC_CLASS_RO$_TestA中赋值为”TestA”
struct objc_ivar_list *ivars成员变量列表
struct objc_method_list **methodLists普通函数表(即非类函数)
struct objc_cache *cache最近使用函数列表,objc_msgsend过程中查找函数地址时使用缓存表

初始化

static void OBJC_CLASS_SETUP_$_TestA(void ) {
OBJC_METACLASS_$_TestA.isa = &
8fc7
amp;OBJC_METACLASS_$_NSObject;
OBJC_METACLASS_$_TestA.superclass = &OBJC_METACLASS_$_NSObject;
OBJC_METACLASS_$_TestA.cache = &_objc_empty_cache;
OBJC_CLASS_$_TestA.isa = &OBJC_METACLASS_$_TestA;
OBJC_CLASS_$_TestA.superclass = &OBJC_CLASS_$_NSObject;
OBJC_CLASS_$_TestA.cache = &_objc_empty_cache;
}


结合静态函数OBJC_CLASS_SETUP_$$_TestA(void)

可以看到OBJC_METACLASS_$_TestA.isa被赋值给了NSObject的meta-class, OBJC_METACLASS_$_TestA.superclass也被赋值给了OBJC_METACLASS_$_NSObject

函数调用的区别

调用方法一:

TestA * instance = [[TestA alloc] init];
[instance instanceMethod];


通过上述讲解,整个过程首先会找到TestA * instance对应的struct objc_object结构体,通过struct objc_object中的isa指针,找到TestA的类对象,然后在TestA类对象的结构体struct objc_class中的method list查找instanceMethod函数。

调用方法二:

[TestA classMethod];


类函数的调用过程:这里会直接找到TestA类对象的结构体struct objc_class中的isa指针,而struct objc_class中的isa指向的是TestA的meta-class即OBJC_METACLASS_$_TestA,再通过查找meta-class的存储的类函数,实现函数的调用。

总结:通过上述讲解,大家可以看出普通的函数地址存储在struct objc_class结构体中methodLists中,而类方法的地址则存储在类对象对应的meta-class中。

让我们继续看meta-class结构体。

meta-class结构体

meta-class结构体的定义

extern "C" __declspec(dllexport) struct _class_t OBJC_METACLASS_$_TestA __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_$_TestA,
};


meta-class结构体的定义和struct objc_class完全相同。

整体结构



希望通过本文,可以加深你对objective c的对象模型的理解,如有错误,请提出,我会及时改正,大家共同学习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: