专栏名称: Adrenine
iOS开发
目录
相关文章推荐
51好读  ›  专栏  ›  Adrenine

iOS 面试题(11):对象内存结构中的 isa 指针是用来做什么的?

Adrenine  · 掘金  ·  · 2017-12-13 08:46

正文

iOS 面试题(11):对象内存结构中的 isa 指针是用来做什么的? 原创 2017-01-19 唐巧 iOS开发by唐巧 问题 Objective-C 对象内存结构中的 isa  指针是用来做什么的,有什么用? 答案 Objective-C 是一门面向对象的编程语言。每一个对象都是一个类的实例。在 Objective-C 语言的内部,每一个对象都有一个名为 isa 的指针,指向该对象的类。每一个类描述了一系列它的实例的特点,包括成员变量的列表,成员函数的列表等。每一个对象都可以接受消息,而对象能够接收的消息列表是保存在它所对应的类中。 在 Xcode 中按Shift + Command + O , 然后输入 NSObject.h 和 objc.h,可以打开 NSObject 的定义头文件,通过头文件我们可以看到,NSObject 就是一个包含 isa 指针的结构体,如下图所示:

按照面向对象语言的设计原则,所有事物都应该是对象(严格来说 Objective-C 并没有完全做到这一点,因为它有象 int, double 这样的简单变量类型,而 Swift 语言,连 int 变量也是对象)。在 Objective-C 语言中,每一个类实际上也是一个对象。每一个类也有一个名为 isa 的指针。每一个类也可以接受消息,例如代码[NSObject alloc] ,就是向 NSObject 这个类发送名为alloc 消息。 在 Xcode 中按Shift + Command + O , 然后输入 runtime.h,可以打开 Class 的定义头文件,通过头文件我们可以看到,Class 也是一个包含 isa 指针的结构体,如下图所示。(图中除了 isa 外还有其它成员变量,但那是为了兼容非 2.0 版的 Objective-C 的遗留逻辑,大家可以忽略它。)
因为类也是一个对象,那它也必须是另一个类的实列,这个类就是元类 (metaclass )。元类保存了类方法的列表。当一个类方法被调用时,元类会首先查找它本身是否有该类方法的实现,如果没有,则该元类会向它的父类查找该方法,直到一直找到继承链的头。 元类 (metaclass ) 也是一个对象,那么元类的 isa 指针又指向哪里呢?为了设计上的完整,所有的元类的 isa 指针都会指向一个根元类 (root metaclass )。根元类 (root metaclass) 本身的 isa 指针指向自己,这样就行成了一个闭环。上面提到,一个对象能够接收的消息列表是保存在它所对应的类中的。在实际编程中,我们几乎不会遇到向元类发消息的情况,那它的 isa 指针在实际上很少用到。不过这么设计保证了面向对象概念在 Objective-C 语言中的完整,即语言中的所有事物都是对象,都有 isa 指针。 我们再来看看继承关系,由于类方法的定义是保存在元类 (metaclass ) 中,而方法调用的规则是,如果该类没有一个方法的实现,则向它的父类继续查找。所以,为了保证父类的类方法可以在子类中可以被调用,所以子类的元类会继承父类的元类,换而言之,类对象和元类对象有着同样的继承关系。 我很想把关系说清楚一些,但是这块儿确实有点绕,我们还是来看图吧,很多时候图象比文字表达起来更为直观。下面这张图或许能够让大家对 isa 和继承的关系清楚一些:
我们可以从图中看出: NSObject 的类中定义了实例方法,例如 -(id)init 方法 和 - (void)dealloc 方法。







请到「今天看啥」查看全文