01 - Runtime

1.0 Runtime介绍

  • 1.1 Runtime简介
     因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时。
     也就是说只有编译器是不够的,还需要一个运行时系统 (runtime system) 来执行编译后的代码。
     这就是 Objective-C Runtime 系统存在的意义,它是整个Objc运行框架的一块基石。
     Runtime基本是用C和汇编写的,可见苹果为了动态系统的高效而作出的努力。

     Runtime其实有两个版本:“modern”和 “legacy”。
     1.我们现在用的 Objective-C 2.0 采用的是现行(Modern)版的Runtime系统,只能运行在 iOS 和 OS X 10.5 之后的64位程序中。
     2.而OS X较老的32位程序仍采用 Objective-C 1中的(早期)Legacy 版本的 Runtime 系统。
     3.这两个版本最大的区别在于当你更改一个类的实例变量的布局时,在早期版本中你需要重新编译它的子类,而现行版就不需要。
     4.苹果和GNU各自维护一个开源的runtime版本,这两个版本之间都在努力的保持一致。
  • 1.2 Runtime总结
   1.OC就是运行时机制
   2.Runtime是消息机制 
   3.OC方法调用的本质就是发送消息
  • 1.3 Objective-C 从三种不同的层级上与 Runtime 系统进行交互
  1.分别是通过 Objective-C 源代码
  2.通过 Foundation 框架的NSObject类定义的方法
  3.通过对 runtime 函数的直接调用。

2.0 Runtime使用

  • 2.1 Runtime作用
总结起来无非是:
可以在运行时,在不继承也不category的情况下,为各种类(包括系统的类)做很多操作,具体包括:
增加
    1.增加函数:class_addMethod
    2.增加实例变量:class_addIvar
    3.增加属性:@dynamic标签,或者class_addMethod,因为属性其实就是由getter和setter函数组成
    4.增加Protocol:class_addProtocol (说实话我真不知道动态增加一个protocol有什么用,-_-!!)
获取
    1.获取函数列表及每个函数的信息(函数指针、函数名等等):class_getClassMethod method_getName ...
    2.获取属性列表及每个属性的信息:class_copyPropertyList property_getName
    3.获取类本身的信息,如类名等:class_getName class_getInstanceSize
    4.获取变量列表及变量信息:class_copyIvarList
    5.获取变量的值
替换:
    1.将实例替换成另一个类:object_setClass
    2.将函数替换成一个函数实现:class_replaceMethod
    3.直接通过char *格式的名称来修改变量的值,而不是通过变量
  • 2.2 Runtime使用细节
  1.使用Runtime则必须导入
    #import <objc/message.h> 或者 #import<objc/runtime.h>
    // 前者包含后者
  2. Runtime函数的命名规则: 谁的事情,谁开头
     例如:   objc_getClass:获取类对象
             objc_getMetaClass:获取元类

3.0 用到的OC常识

  • 3.1 OC常识
   1. OC对象方法都保存在类对象中方法列表中,OC对象中类方法保存在元类(meta)
 2. OC中所有方法最终都会转换成函数
  3. 内存五大区:栈,堆,常量区,全局区,方法区
      a. 栈:自动管理内存
      b. 堆:手动管理内存
  • 3.2 OC方法调用流程:
   1.根据对象的isa去对应类对象去查找方法, isa:指向类对象
   2.根据传入方法编号,去类对象中方法列表中查找对应方法
   3.调用方法实现
OC方法调用流程

4.0 Runtime常用方法示例

  • 4.1 Runtime(消息机制)
  • 首先,你需要知道这两个概念:
 1.OC中调用方法就是向对象发送消息。
          比如 :[person run];
          这实际上这是在给person这个对象发送run这个消息。
  2.当run这个方法只有定义没有实现就会报错:
          Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person run]: unrecognized selector sent to instance
  • 经典消息发送

  • 消息转发

  • 4.2 获取类的所有方法列表

    获取到的数据是一个Method数组,Method数据结构中包含了函数的名称、参数、返回值等信息,以下代码以获取名称为例:
    

u_int count;
Method * methods= class_copyMethodList([UIView class], &count);
for (int i = 0; i < count ; i++)
{
SEL name = method_getName(methods[i]);
NSString *strName = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
NSLog(@"%@",strName);
}


- 4.3 Runtime(交换方法)
 - 交换方法实现 : 调用A的方法名但是会去执行B的方法.
 -  ###### !!!友情提醒 : 不要为了使用runtime,而去使用(超级容易坑队友)
 - 使用的一些场景 : 
- 

1.给系统的方法增加功能

  • 例如 : 给UIImage的imageNamed方法提供一个功能,加载图片的时候,会告诉开发者是否加载功能

    //TODO: 在原来加载图片功能之上,在添加一个判断是否加载成功功能
    1.自定义类,重写系统方法 弊端:1.每次使用,都需要导入
    2.给UIImage提供分类,扩充方法 弊端:1.每次使用,都需要导入
    tips: 2.1 在分类中,重写系统方法实现,会导致系统方法被干掉
    2.2 在分类中,重写系统方法实现,容易坑到队友,慎用
    3.交换方法 交换imageNamed和bl_imageNamed实现
    3.1 根据OC方法调用的流程,我们只需要交换方法列表映射就可以实现方法交换

![交换方法实现原理](http://upload-images.jianshu.io/upload_images/1832614-588edb92e310123c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

Runtime代码实现方法交换 :

ViewController.m 文件

@implementation ViewController

  • (void)viewDidLoad {
    [super viewDidLoad];
    // bl_imageNamed有加载图片和判断功能
    [UIImage imageNamed:@"123"];
    }

UIImage+Image.m 文件

import "UIImage+Image.h"

import <objc/message.h>

@implementation UIImage (Image)

/*load方法特性:
 1.程序一开始启动,就会把所有类加载进内存,此时就会调用load方法
 2.只会调用一次
 */
  • (void)load
    {
    // 所有方法都保存在类中
    // Class:获取哪个类方法 [xxxx class]
    // SEL:获取哪个方法

    Method imageNameMethod = class_getClassMethod(self, @selector(imageNamed:));
    Method bl_imageNameMethod = class_getClassMethod(self, @selector(bl_imageNamed:));

    // 交换imageNamed和bl_imageNamed实现
    method_exchangeImplementations(imageNameMethod, bl_imageNameMethod);
    }

  • (UIImage *)bl_imageNamed:(NSString *)name
    {
    // 1.加载图片
    // 2.由于交换了映射 :在bl_imageNamed方法内部调用bl_imageNamed,实际是调用了imageNamed
    UIImage *image = [UIImage bl_imageNamed:name];

    // 3.判断是否加载成功
    if (image == nil) {
    NSLog(@"加载失败");
    } else {
    NSLog(@"加载成功");
    }
    return image;
    }


- TODO : Runtime(动态添加方法)

留坑


- TODO :Runtime(动态添加属性)


留坑

- ### Runtime 一些常见的问题与解决方法

Q1 : 怎么才能让消息机制函数有参数提示?
A1 : runtime的消息机制函数,在xcode6之后就没有提示参数
S1 : 点击工程文件 -> build Setting -> 搜索msg -> Enable Strict Checking of objc_msgSend Calls(不要严肃检查消息机制调用) -> NO

OC_runtime运行时官方文档翻译:http://www.ithao123.cn/content-801906.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,636评论 0 9
  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 3,674评论 7 64
  • 转载:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麦子阅读 694评论 0 2
  • 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的...
    西木阅读 30,470评论 33 467
  • 孩子们开心,爸爸妈妈就放心了 1, 糖糖第二天醒来的时候,泰迪熊先生已经不见了。她有些失落,觉得自己可能是做了一个...
    小馋妈阅读 893评论 6 6