文章目录
  1. 1. Objective-C类和对象的实现原理
    1. 1.1. Class结构
    2. 1.2. 类的继承
    3. 1.3. 总结

Objective-C类和对象的实现原理

我是LastDays,我的博客:LastDays.cn

最近一直在了解runtime的实现原理,所以简单的分享一下。

Objective-C的runtime是开源的,但是开始的时候并没有开源NSObject底层的实现,但是后来objc4-532.2发布后,苹果也将NSObject的实现原理加了进来

在这里可以下载Runtime的源码:objc4

Class结构

runtime中NSObject.mm中的一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@protocol NSObject

- (BOOL)isEqual:(id)object;
- (NSUInteger)hash;

- (Class)superclass;
- (Class)class;
- (id)self;
- (NSZone *)zone;

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

- (BOOL)isProxy;

- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;

- (BOOL)respondsToSelector:(SEL)aSelector;

- (id)retain;
- (oneway void)release;
- (id)autorelease;
- (NSUInteger)retainCount;

- (NSString *)description;
- (NSString *)debugDescription;

@end

OBJC_EXPORT
@interface NSObject <NSObject>
{
Class isa;
}
@end

这段代码中

1
2
3
4
5
@interface NSObject <NSObject>
{
Class isa;
}
@end

引起了我的关注,接着发现runtime中声明了id和Class两种类型:

1
2
3
4
5
6
7
8
9
10
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

/// Represents an instance of a class.
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;

在runtime的objc.h中

1
2
3
4
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;

其实,Objective-C中的对象就是一个结构体,并且所有的对象都有一个相同的结构体。其实,Class就是类,id就是对象。而且我们可以看到每一个对象都有一个isa指针,这是这个isa就是指向该类。

看一下objc_class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct objc_class {
Class isa;

#if !__OBJC2__
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;
#endif

} OBJC2_UNAVAILABLE;

进行一下简单的描述(如果不对希望大家能够指出)

  • super_class 父类
  • name 类名
  • version 类版本信息(默认为0)
  • info 类信息
  • instance_size 实例变量大小
  • ivars 成员变量
  • methodLists 方法
  • cache 方法缓存
  • protocols 协议

在这里我们同样也看到了一个isa指针,他被称为元类。这里Class其实看起来就像是一个对象,需要有地方去存储它的方法列表,类名等信息。那么元类就是Class的isa指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@interface LastDays : NSObject

@property NSString *name;

-(void)showName1;

+(void)showName2;

@end


@implementation LastDays

-(void)showName1{
NSLog(@"类");
}

+(void)showName2{
NSLog(@"元类");
}

@end

所有LastDays的实例化对象的isa都指向LastDays(类),LastDays中记录着父类类名,类版本信息(默认为0),类信息,实例变量大小,成员变量,方法,方法缓存,协议等信息,那么LastDays中的isa指向了元类,元类中只记录着类名,类方法列表等,所有的元类指向一个根元类,根元类的isa指向自己,这样就实现了一个封闭的内循环

举例说明:

1
2
3
4
5
Lastdays *ly = [[LastDays] alloc] init]; //初始化ly

[ly showName1];//发送showName1消息时,ly变量中的isa会遍历LastDays中的类方法列表找到showName1

[LastDays showName2];//发送showName2时,LastDays的isa指针会遍历LastDays的元类类方法

类的继承

关于类的继承,其实我们可以根据类的实现可以推断出来。

objc_class结构中我们可以发现有一个super_class指针,其实这个指针是指向我们的父类。

我们设计这么一种继承结构: LastDays:Last:NSObject

如图所示就是继承实现的原理:

通过以上图形,根据蓝线我们可以看出,每个对象的isa都不为空,这样只要是有一个id类型的对象,通过runtime机制都可以获取该对象。

根据黑线我们可以看出,最终继承自NSObject,并且NSObject的superclass为nil。

同样也有很多公开的函数可以访问类信息

例如:输出类方法

1
2
3
4
5
6
7
8
9
10
11
void PrintObjectMethods() {
unsigned int count = 0;
Method *methods = class_copyMethodList(self,
&count);
for (unsigned int i = 0; i < count; ++i) {
SEL sel = method_getName(methods[i]);
const char *name = sel_getName(sel);
printf("%s\n", name);
}
free(methods);
}

总结

以上就是我对Objective-C类和对象的实现原理的理解,有什么问题或者错误欢迎大家在评论处指出。

文章目录
  1. 1. Objective-C类和对象的实现原理
    1. 1.1. Class结构
    2. 1.2. 类的继承
    3. 1.3. 总结