iOS开发之runtime运行时机制
最近参加三次面试都有被问到runtime,因为不太懂runtime我就只能支支吾吾的说点零碎。我真的好几次努力想看一看runtime的知识,因为知道理解它对理解OC代码内部变化有一定帮助,不过真心觉得对开发没啥意义和用处,又是纯C的代码,现在开源项目那么多,基本都能参考别人的代码达到自己的目的。不过为了面试,今天硬着头皮稍微学了点,才算明白一点runtime的强大之处,现在大致知道它可以用来归档解档,以及字典转模型等。勉强写写今天的一点收获总结吧,依然很零碎,看官请自便。我发现这篇文章不错,看了几篇关于runtime的文章,这篇我感觉稍微通熟易懂一点,地址:《Objective-C特性:Runtime》,如果想了解更多请参考这篇吧。
什么是runtime(运行时机制)
Objective-C是基于C语言加入了面向对象特性和消息转发机制的动态语言,这意味着它不仅需要一个编译器,还需要Runtime系统来动态创建类和对象,进行消息发送和转发。
1.runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。
2.平时编写的OC代码, 在程序运行过程中, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者
runtime的作用
runtime是属于OC的底层, 可以进行一些非常底层的操作(用OC是无法现实的, 不好实现)。
1.在程序运行过程中, 动态创建一个类(比如KVO的底层实现)
2.在程序运行过程中, 动态地为某个类添加属性\方法, 修改属性值\方法
3.遍历一个类的所有成员变量(属性)\所有方法
runtime相关应用
* NSCoding(归档和解档, 利用runtime遍历模型对象的所有属性)
* 字典 --> 模型 (利用runtime遍历模型对象的所有属性, 根据属性名从字典中取出对应的值, 设置到模型的属性上)
* KVO(利用runtime动态产生一个类)
* 用于封装框架(想怎么改就怎么改)
Runtime数据结构
在Objective-C中,使用[receiver message]语法并不会马上执行receiver对象的message方法的代码,而是向receiver发送一条message消息,这条消息可能由receiver来处理,也可能由转发给其他对象来处理,也有可能假装没有接收到这条消息而没有处理。其实[receiver message]被编译器转化为:
id objc_msgSend ( id self, SEL op, ... );
下面简单介绍runtime中重要的数据结构:
|
SEL |
表示方法选择器。其实它就是映射到方法的C字符串,你可以通过Objc编译器命令@selector()或者Runtime系统的sel_registerName函数来获取一个SEL类型的方法选择器。 |
|
id |
id是通用类型指针,能够表示任何对象。id其实就是一个指向objc_object结构体指针,它包含一个Class isa成员,根据isa指针就可以顺藤摸瓜找到对象所属的类。 |
|
Class |
Class表示对象所属的类。可以查看到Class其实就是一个objc_class结构体指针。在面向对象设计中,一切都是对象,Class在设计中本身也是一个对象。 |
|
Method |
Method表示类中的某个方法。其实Method就是一个指向objc_method结构体指针,它存储了方法名(method_name)、方法类型(method_types)和方法实现(method_imp)等信息。 |
|
Ivar |
Ivar表示类中的实例变量。Ivar其实就是一个指向objc_ivar结构体指针,它包含了变量名(ivar_name)、变量类型(ivar_type)等信息。 |
|
IMP |
IMP本质上就是一个函数指针,指向方法的实现。当你向某个对象发送一条信息,可以由这个函数指针来指定方法的实现,它最终就会执行那段代码,这样可以绕开消息传递阶段而去执行另一个方法实现。 |
|
Cache |
Cache主要用来缓存。Cache其实就是一个存储Method的链表,主要是为了优化方法调用的性能。当调用方法时,优先在Cache查找,如果没有找到,再到methodLists查找。 |
Runtime消息发送
前面从objc_msgSend作为入口,逐步深入分析Runtime的数据结构,了解每个数据结构的作用和它们之间关系后,我们正式转入消息发送这个正题。
objc_msgSend函数
在前面已经提过,当某个对象使用语法[receiver message]来调用某个方法时,其实[receiver message]被编译器转化为:
id objc_msgSend ( id self, SEL op, ... );
现在让我们看一下objc_msgSend它具体是如何发送消息:
1.首先根据receiver对象的isa指针获取它对应的class
2.优先在class的cache查找message方法,如果找不到,再到methodLists查找
3.如果没有在class找到,再到super_class查找
4.一旦找到message这个方法,就执行它实现的IMP。

方法解析与消息转发
[receiver message]调用方法时,如果在message方法在receiver对象的类继承体系中没有找到方法,那怎么办?一般情况下,程序在运行时就会Crash掉,抛出 unrecognized selector sent to …类似这样的异常信息。但在抛出异常之前,还有三次机会按以下顺序让你拯救程序。
1.Method Resolution
2.Fast Forwarding
3.Normal Forwarding

三种方法的选择
Runtime提供三种方式来将原来的方法实现代替掉,那该怎样选择它们呢?
1.Method Resolution:由于Method Resolution不能像消息转发那样可以交给其他对象来处理,所以只适用于在原来的类中代替掉。
2.Fast Forwarding:它可以将消息处理转发给其他对象,使用范围更广,不只是限于原来的对象。
3.Normal Forwarding:它跟Fast Forwarding一样可以消息转发,但它能通过NSInvocation对象获取更多消息发送的信息,例如:target、selector、arguments和返回值等信息。
Method Swizzling
Method Swizzling就是在运行时将一个方法的实现代替为另一个方法的实现。如果能够利用好这个技巧,可以写出简洁、有效且维护性更好的代码。
总结
虽然在平时项目不是经常用到Objective-C的Runtime特性,但当你阅读一些iOS开源项目时,你就会发现很多时候都会用到。所以深入理解Objective-C的Runtime数据结构、消息转发机制有助于你更容易地阅读和学习开源项目。
iOS开发之runtime运行时机制的更多相关文章
- runtime 运行时机制 完全解读
runtime 运行时机制 完全解读 目录[-] import import 我们前面已经讲过一篇runtime 原理,现在这篇文章主要介绍的是runtime是什么以及怎么用!希望对读者有所帮助! ...
- iOS开发之Runtime机制深入解析
本篇主要讲述在 OC 开发中主要涉及到的运行时机制: 运行时的工作: 运行时在 OC 中的工作:OC 语言的设计模式决定了尽可能的把程序从编译和链接时推迟到运行时.只要有可能,OC 总是使用动态的方式 ...
- iOS开发之Runtime使用
runtime简介 RunTime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C语言,函数的调用在编译的时候会决定调用哪个函数. 对于OC的函数,属于动态 ...
- Runtime运行时机制
Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的 我们需要了解的是 Objective-C 是一门动态语言, ...
- iOS-浅谈runtime运行时机制-runtime简单使用(转)
转自http://www.cnblogs.com/guoxiao/p/3583432.html 由于OC是运行时语言,只有在程序运行时,才会去确定对象的类型,并调用类与对象相应的方法.利用runtim ...
- iOS开发之Runtime常用示例总结
经常有小伙伴私下在Q上问一些关于Runtime的东西,问我有没有Runtime的相关博客,之前还真没正儿八经的总结过.之前只是在解析第三方框架源码时,聊过一些用法,也就是这些第三方框架中用到的Runt ...
- iOS-浅谈runtime运行时机制02-runtime简单使用
http://blog.csdn.net/jiajiayouba/article/details/44201079 由于OC是运行时语言,只有在程序运行时,才会去确定对象的类型,并调用类与对象相应的方 ...
- iOS开发之runtime的运用-获取当前网络状态
之前写过runtime的一些东西,这次通过runtime获取一些苹果官方不想让你拿到的东西,比如,状态栏内部的控件属性.本文将通过runtime带你一步步拿到状态栏中显示网络状态的控件,然后通过监测该 ...
- iOS开发之Runtime函数
1.可以通过NSObject的一些方法获取运行时信息或动态执行一些消息: 1./*Returns a Boolean value that indicates whether the receivin ...
随机推荐
- for( unsigned int i=heapSize/2-1; i>=0; --i)
unsigned int的表示 今天在写堆排序的时候遇到一个BUG void builMaxHeap( int *arr,unsigned int heapSize){ unsigned int i; ...
- 【bzoj1059】矩形游戏
题意 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏--矩阵游戏.矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种操作:行交换操作 ...
- iOS动态部署方案
转载: iOS动态部署方案 前言 这里讨论的动态部署方案,就是指通过不发版的方式,将新的内容.新的业务流程部署进已发布的App.因为苹果的审核周期比较长,而且苹果的限制比较多,业界在这里也没有特别多的 ...
- jmeter 构建一个Web测试计划
添加用户 第一步你想做的每一个JMeter测试计划是添加一个 线程组 元素. 线程组告诉 JMeter的用户数量你想模拟,用户应该发送的次数 请求,请求他们应该送多少. 继续添加ThreadGroup ...
- postgresql 触发器
一.创建事件触发器 1.ddl_command_start - 一个DDL开始执行前被触发: 2.ddl_command_end - 一个DLL 执行完成后被触发: 3.sql_drop -- 删除一 ...
- (32)odoo中的编码问题
对于全部是英文就不存在问题,但我们常用中文,这样会导致一个棘手的问题 约定: 系统Ubuntu trusty14.04 自带python2.7.6 python2.7.9 自己升级了 升级方法: -- ...
- hdu------1281 棋盘游戏(最小覆盖点)
棋盘游戏 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDUOJ-------2719The Seven Percent Solution
The Seven Percent Solution Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- Struts2动态结果(${})and全局结果(global-results)
动态结果 例:根据判定动态结果区分用户进行登录 1.先在TestAction类中进行判定赋值 public class TestAction extends ActionSupport { priva ...
- 创建交货单/外向交货BAPI_OUTB_DELIVERY_CREATE_SLS/STO
FUNCTION Z_SD_CREATE_DN. *"-------------------------------------------------------------------- ...