Objective-C--Runtime机制
个人理解:
简单来说,Objective-C runtime是一个实现Objective-C语言的C库。对象可以用C语言中的结构体表示,而方法(methods)可以用C函数实现。事实上,他们 差不多也是这么干了,另外再加上了一些额外的特性。这些结构体和函数被runtime函数封装后,Objective-C程序员可以在程序运行时创建,检 查,修改类,对象和它们的方法。例如一个普通类,我们写好之后,Runtime会进行处理。最后变成以下结构:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#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;
通过一个结构体的方式,来存放类中的信息。
再比如,我们调用的实例方法。从本质上来看是用C语言中的函数来实现的,但是在外面我们还是对实例方法使用结构体进行了封装。结构体如下:
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE;//函数名
char *method_types OBJC2_UNAVAILABLE;//method_types是个char指针,存储着方法的参数类型和返回值类型。
IMP method_imp OBJC2_UNAVAILABLE;//函数指针,指向这个函数的首地址
}
在重复一下,Objective-C runtime是一个实现Objective-C语言的C库。
几个知识点的简要概述:
Object & Class & Meta Class
什么是Object?
在oc中有一个id的概念。他的定义为:
typedef struct objc_object *id;
struct objc_object {
Class isa;
};
Objective-C中的object在最后会被转换成C的结构体,而在这个struct中有一个 isa 指针,指向它的类别 Class。
什么是Class?
typedef struct objc_class *Class;
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#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;
上面是类在runtime中的源代码,从这看,类其实也是一个结构体。这个结构体中的isa指向一个Metaclass。
什么是Metaclass?
仔细一看,发现 Class isa,原来,isa(Metaclass)的源码还是类的源码:
typedef struct objc_class *Class;
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#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;
Object, Class, MetaClass三者之间的关系?
Class存放类信息,方法数组存放实例方法;Meta Class存放类信息,方法数组存放类方法。
每一个object都有一个isa指针,isa指针指向自己的Class 每个Class都有一个isa指针指向一个唯一的Meta Class
- 每一个Meta Class的isa指针都指向最上层的Meta Class(图中的NSObject的Meta Class) 最上层的Meta
- Class的isa指针指向自己,形成一个回路 每一个Meta Class的super class指针指向它原本Class的 Super
- Class的Meta Class。但是最上层的Meta Class的 Super Class指向NSObject Class本身
- 最上层的NSObject Class的super class指向 nil
objective-C中的消息机制?
什么是SEL?
typedef struct objc_selector *SEL;
SEL是一个指向objc_selector结构体的指针。而 objc_selector 的定义并没有在runtime.h中给出定义。
编译器会根据每个方法的方法名为那个方法生成唯一的SEL。只要方法名相同,那么它的SEL就是一样的。每一个方法都对应着一个SEL。
什么是IMP?
typedef id (*IMP)(id, SEL, …);
IMP本质就是一个函数指针,这个被指向的函数包含一个接收消息的对象id,调用方法的SEL,以及一些方法参数,并返回一个id。因此我们可以通过SEL获得它所对应的IMP,在取得了函数指针之后,也就意味着我们取得了需要执行方法的代码入口,这样我们就可以像普通的C语言函数调用一样使用这个函数指针。
类中的方法存储?
什么是方法?
typedef struct objc_method *Method;
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE;
char *method_types OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE;
方法存放位置?
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#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; OBJC2_UNAVAILABLE;
在创建一个类的时候,我们将类中的实例方法存放到objc_class结构体(类的结构体,前面提到)中的objc_method_list **methodLists中。将类中的类方法存放到相应的MetaClass中的类结构中的objc_method_list **methodLists中。我们可以理解为objc_class中 method list保存了一组SEL<->IMP的映射。
调用方法的具体步骤?
在Objective-C中,消息直到运行时才会绑定到方法的实现上。编译器会把代码中[target doSth]转换成 objc_msgSend消息函数,这个函数完成了动态绑定的所有事情。它的运行流程如下:
- 检查selector是否需要忽略。(ps: Mac开发中开启GC就会忽略retain,release方法。)
- 检查target是否为nil。如果为nil,直接cleanup,然后return。(这就是我们可以向nil发送消息的原因。)
- 然后在target的Class中根据Selector去找IMP
寻找IMP的过程:
- 先从当前class的cache方法列表(cache methodLists)里去找
- 找到了,跳到对应函数实现
- 没找到,就从class的方法列表(methodLists)里找
- 还找不到,就到super class的方法列表里找,直到找到基类(NSObject)为止
- 最后再找不到,就会进入动态方法解析和消息转发的机制。(这部分知识,http://southpeak.github.io/blog/2014/11/06/objective-c-runtime-yun-xing-shi-zhi-si-:method-swizzling/)
objective-C中的Category?
看Category的源码,不用想就知道这个又是一个结构体
typedef struct objc_category *Category;
struct objc_category {
char *category_name OBJC2_UNAVAILABLE;//分类名
char *class_name OBJC2_UNAVAILABLE;//类名
struct objc_method_list *instance_methods OBJC2_UNAVAILABLE;//实例方法列表
struct objc_method_list *class_methods OBJC2_UNAVAILABLE;//类方法列表
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;//协议列表
}
运行过程:
- 加载Category
- 将Category加载到所属的类中
- 将Category中的方法加载到Class或者MetaClass结构体中的方法列表中
(具体看这里的运行代码)
objective-C中的成员变量与属性?
什么是成员变量?
typedef struct objc_ivar *Ivar;
struct objc_ivar {
char *ivar_name OBJC2_UNAVAILABLE;
char *ivar_type OBJC2_UNAVAILABLE;
int ivar_offset OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
}
这里我们注意第三个成员 ivar_offset。它表示基地址偏移字节。我们通过字节偏移量来获取变量的地址。(具体方式不展开)
成员变量存放位置?
存放在之前我们仿佛强调的objc_class中的struct objc_ivar_list *ivars中 。
属性和成员变量的区别?
类中的Property属性被编译器转换成了Ivar,并且自动添加了我们熟悉的Set和Get方法。
讲解Runtime,结合代码和题目
http://www.cocoachina.com/ios/20141224/10740.html
刨根问底Objective-C Runtime(1)- Self & Super
刨根问底Objective-C Runtime(2)- Object & Class & Meta Class
刨根问底Objective-C Runtime(3)- 消息和Category
刨根问底Objective-C Runtime(4)- 成员变量与属性
这一系列文章中,讲的很全面,但是没有结合源代码具体来看
Objective-C Runtime 运行时之一:类与对象
Objective-C Runtime 运行时之二:成员变量与属性
Objective-C Runtime 运行时之三:方法与消息
Objective-C Runtime 运行时之四:Method Swizzling
Objective-C--Runtime机制的更多相关文章
- Objective-C的对象模型和runtime机制
内容列表 对象模型(结构定义,类对象.元类和实例对象的关系) 消息传递和转发机制 runtime系统功能理解 对象模型 结构定义 对象(Object): OC中基本构造单元 (building blo ...
- iOS开发之深入探讨runtime机制02-runtime的简单使用
runtime机制为我们提供了一系列的方法让我们可以在程序运行时动态修改类.对象中的所有属性.方法. 下面就介绍运行时一种很常见的使用方式,字典转模型.当然,你可能会说,“我用KVO直接 setVal ...
- iOS开发之深入探讨runtime机制01-类与对象
最近有个同事问我关于“runtime机制”的问题,我想可能很多人对这个都不是太清楚,在这里,和大家分享一下我对于runtime机制的理解.要深入理解runtime,首先要从最基本的类与对象开始,本文将 ...
- Runtime机制的使用整理
一.基本概念 1.1.RunTime简称运行时,就是系统在运行的时候的一些机制,其中最主要的是消息机制. 1.2.对于C语言,函数的调用在编译的时候会决定调用哪个函数,编译完成之后直接顺序执行,无任何 ...
- iOS的Runtime机制下给类别(category)添加属性、替换原有类的方法执行
一.Runtime的理解 OC是面向对象的语言这是常识,其实就是通过Runtime机制动态创建类和对象,这里只是简单的运用runtime的使用! 二.类别(category)添加属性_使用前记得导入头 ...
- Runtime机制之结构体及操作函数
一.动态语言 Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:具有灵活性,比如:消息转发,方法交换等.它有一个运行时系统Ob ...
- Objective C Runtime 开发介绍
简介 Objective c 语言尽可能的把决定从编译推迟到链接到运行时.只要可能,它就会动态的处理事情.这就意味着它不仅仅需要一个编译器,也需要一个运行时系统来执行变异好的代码.运行时系统就好像是O ...
- Objective-C runtime 机制
Runtime使用C语言结构体表示对象,用C语言函数表示方法,这些C语言函数和结构体被Runtime封装后,我们就可以在程序中执行创建,检查,修改类和对象和他们的方法 OC的Class其实是一个obj ...
- runtime机制
runtime(简称运行时),是一套 纯C(C和汇编写的) 的API.而 OC 就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 消息机制原理:对象根据方法编号SEL去映射表查找对 ...
- iOS开发之Runtime机制深入解析
本篇主要讲述在 OC 开发中主要涉及到的运行时机制: 运行时的工作: 运行时在 OC 中的工作:OC 语言的设计模式决定了尽可能的把程序从编译和链接时推迟到运行时.只要有可能,OC 总是使用动态的方式 ...
随机推荐
- 关于Keil的安装与注册
由于前一段时间一直在做关于stm32f407的相关内容,于是安装的Keil是MDK5,最近一阵子想再看看51单片机以前没有做过的内容,就要再安装一个Keil C51,结果就不可避免的遇到了两个软件必须 ...
- windows“画图”工具用法
图片编辑工具不少,photoshop功能强大,但是并不是那么容易掌握.而且,倘若一个简单的图片处理问题就使用这么强大的工具,有点“杀鸡焉用牛刀”的意思,要知道只打开photoshop就需要一段等待时间 ...
- Linux脚本
放置在/usr/local/sbin下面: 收到一个问题:"-bash XXX 没有权限":需要在此目录下执行chmod +x filename 收到一个问题:"-bas ...
- Quartz1.8.5例子(六)
/* * Copyright 2005 - 2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the ...
- 切换view的动画
代码: #import "MainViewController.h" @interface MainViewController () @end @implementation M ...
- android学习小例子——验证码倒计时按钮
1.activity_main.xml: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/andro ...
- GNOME Shell叫板Ubuntu Unity:优劣PK
转自GNOME Shell叫板Ubuntu Unity:优劣PK GNOME Shell 对阵 Ubuntu Unity--默认桌面界面的战火一触即发.双方在台上已经对峙了很长时间,现在是时候决定谁会 ...
- Python3.x和Python2.x的区别-转
这个星期开始学习Python了,因为看的书都是基于Python2.x,而且我安装的是Python3.1,所以书上写的地方好多都不适用于Python3.1,特意在Google上search了一下3.x和 ...
- C模块划分
模块划分的"划"是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独立的部分合作完成系统的需求.C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能(依功能进行 ...
- Spark Streaming 结合FlumeNG使用实例
SparkStreaming是一个对实时数据流进行高通量.容错处理的流式处理系统,可以对多种数据源(如Kdfka.Flume.Twitter.Zero和TCP 套接字)进行类似map.reduce.j ...