Runtime-b

感谢大神分享

依旧是网上很多runtime的资料,依旧是看不懂,,,这里给大家转化一下runtime,使它由隐晦难懂变得通俗易懂。

(虽然截图和语言组织的有些凌乱,但是大家还是一点一点的阅读下去吧,可以新建一个工程,跟着我写的一步一步的自己走一遍,会有帮助的。)

关于runtime理论性的东西可以参考我们同事hah的初识runtime(我俩的文章名字居然差不多)

本文参照:教你快速上手Runtime。谢谢该文作者峥吖峥老师。有兴趣的也可以去峥老师的博客看看去。

另外哪里写的不对,可以给我留言,我会及时改进的,谢谢大家。

在这里我们对runtime进行如下的介绍:

1、runtime的简单介绍

2、runtime的消息发送

3、用runtime交换方法

4、动态添加方法

5、动态添加属性

6、runtime替换KVC,进行字典转换

 

下边开始我们的通俗易懂的路程:

1、配置环境:新建一个工程,在appdelegate里面将viewcontroller设置为rootcontroller,方便查看打印信息。

创建一个person类,继承自NSObject,下图的PersonViewController无用。

然后再看一下目前的工程文件结构:

按照网上教程我们开始runtime的各个方法的实现。

2、发送消息。举例:实例方法和类方法的调用原理。

我们建立一个继承于NSObject的Person

在.m中分别实现实例方法和类方法:

然后在viewcontroller加入头文件:#import "Person.h"、#import <objc/message.h>

方法的调用有两种,调用实例方法和调用类方法。我们用runtime去观察这两种方法的实质。

1、viewDidLoad里面实现Person的实例化,并用这个实例调用Person里面的实例方法;

2、直接用Preson类名或类对象调用类方法。

此时我们可以看到

但是按照网上教程上图蓝色框框里面的也应该可以放开注释的,可是不知道为什么我的放开注释以后会爆红:

不知道是为什么(如果大家谁知道怎么回事,还烦请留言告诉我,再次谢谢大家了),,,所以这里的runtime并不友好。

哎,终于知道怎么回事了,还是同事hah帮忙解决的:头文件导入错了,应该是导入:#import <objc/runtime.h>

导入#import<objc/messge.h>也可以调用objc_msgSend()这个方法,但是不能传参,而导入#import<objc/runtime.h>,会出现这个方法:objc_msgSend(id, SEL, ...),是可以传参数的.

在这里有的网友提到另外一种解决该问题的方案:谢谢北京-吴露。方案是:引入头文件<objc/objc-runtime>,command+点击进入这个方法,我们会看到下边的

也就是说这个头文件把runtime和message都包含了,不过建议还是单独引入,因为这两个头文件里面的方法很多都类似,容易混淆,区别在于方法是否可以传参数。就像上边我们举例的问题。

打印结果:

其实这里咱们可以看到网上教程的注释:不管是实例方法还是类方法,其本质就是让对象或者类对象发送消息,即我们在OC中调用的实例方法和类方法在runtime运行时的时候实际上是转化成C语言的发送消息的语句。

按照网上教程说的:消息机制原理:对象根据方法编号SEL去映射表查找对应的方法实现

其实说的就是:找到对应的实例方法或者类方法。

最后,这里的runtime的使用并不实用

3、交换方法。

其实写完下边的代码,在通过理解,你会发现这中所谓的“交换方法”实际上就是系统方法的重写、扩展、再替换回去的过程。

首先我们看一下demo里面viewcontroller的结构(同样的personviewcontroller无用,忽略掉,这里的<objc/message.h>最好是换成#import<objc/runtime.h>):

然后我们看viewDidLoad里面,在这里我们没有做什么操作,只是命名了一个image:这里我们的图片是在工程文件中的,所以走到替换方法里面的时候会判断不为空,所以对应的打印信息“加载空的图片”就不会打印出来。

按照网上教程我们进行步骤一的操作,写一个名字叫做+ (instancetype)imageWithName:(NSString*)name的类方法。这个方法是为了替换的时候准备的。

然后我们进行步骤二,这个步骤二很关键,就是替换的核心所在。

注意:两个方法。前面一个是准备好的方法,后边一个是系统的方法,要用第一个方法换掉第二个方法,这里需要注意替换顺序。

当我们将viewDidLoad里面的image换成一个空的图片的时候

我们看到打印信息

是走了图片为空的if判断里面的。

所以,这个方法可以看成是网络请求一张图片,如果请求失败,可以用默认的图片进行展示,就像下边的方法,网络请求失败的时候会展示一张默认图。

当然,这里不是说runtime这么高大上的方法仅仅能实现这么low的功能,仅做示例而已。

其实这个方法替换可以用在线下替换线上代码里面,“黑魔法”,我还不会,只是听说过。下边继续学习runtime其他的方法。

4、动态添加方法。

动态添加方法,咱们的person类.h里面用到了分类:

在这里拓展一下类扩展的知识:类扩展与分类的区别。谢谢作者:Mitchell孟晨

在这里大家是不是会想到我们的面试题中:

有的还是用英语问的:

类的作用。参考自category解析。如果大家对类别特别感兴趣可以参考深入解析OC中的Category

当我们在类中添加@interface的时候:

会出现上图中的3个。

第一个就是类:继承自谁。

第二个是分类,就是分类。

类扩展与分类的区别中有举例说明:虽然我们在分类中声明属性不会报错,但是@property并没有自动为我们设置的属性生成set、get方法。

第三个就是extension。类扩展。

再看上述中有一句话是这样说的:

类扩展的作用:

person类.m中:

viewcontroller里面:

这里没有实现eat4方法,所以会在viewcontroller中的viewdidload里面调用eat4的时候,会调用这个方法处理,并且把对应的方法列表传过来。用来判断为实现的方法是不是我们想要动态添加的方法。

这里注意的是,峥老师教程里面在调用class_addMethod(self,@selector(eat4), (IMP)eatt,"[email protected]:");这个方法的时候,第三个参数前面并没有添加“(IMP)”,不添加这个IMP,会报黄:

说的什么不清楚,意思就是叫你添加上IMP。

拓展一下performSelector调用和直接调用的区别:

准备好了,我们看打印结果:

这里我们可以看到NSStringFromSelector(sel)调用的就是eat4。

扯了这么多怎么用,到底这个动态添加方法到底是用来干什么的呢,看看众多网友的理解。翻了好多,就下边的两个解释比较靠谱,大家凑合着看吧:

当然还有最一开始咱们引入动态添加的时候的目的:

不忘初心,方得始终。

5、动态添加属性。

想知道原理的请移步OC Associated Objects实现原理

原理:给一个类声明属性,其实本质就是给这个类添加关联,并不是直接把这个值的内存空间添加到类存空间。

看结构,添加了一个NSObject的分类:

分类的.h文件,将set方法和name外漏,方便在viewcontroller里面调用。

分类的.m文件,set方法和name的实现。

最后看viewcontroller里面,引入分类的头文件,然后实例化NSObject,调用objc1的name。

最后的打印结果:

tips:其实呢这个动态添加属性,是在哪里用到的呢?具体的我也说不上来。其实按照我的理解,咱们这里所谓的动态添加属性,是在分类上边添加的属性,那么我就想了,为什么我不能在类自己本身上边添加属性呢?对吧?为什么非要在分类上边添加呢,还整了个动态添加属性,麻烦不?!原因有两个:

1)如果你的类自己本身里面的逻辑或者代码比较多,而需求是新加一个功能,那么就可以在分类上边添加,因为分类和继承还是有区别的。咱们这样理解啊:如果你用的是继承,那么在子类a里面新添加的属性和方法,在父类以及其他继承父类的子类b里面是不能用新添加的属性和方法的,(有点绕)。但是分类就行,你在分类里面新添加了属性和方法,那么在其他用到这个类自己的地方,是可以用新添加的属性和方法的。好像和公有性、私有性有点关系。

2)给系统的类添加属性。像UIView、UIImageView、UILabel、UIButton等等系统的类,你觉得系统的类里面的属性不够用(当然,像我这种小白还是觉得够用的,关键不知道各个类里面除了经常用的还有啥,,,)就可以自己添加属性,当然了,在MJ和SDWebimage里面其实也能看到动态添加属性的影子,只不过是我们大多数人没有进入人家里面去看具体的代码。同事hah在runtime初识里面也提到了这个:

6、字典转模型

峥老师说的“字典转模型的方式一:KVC”这个就是咱们平时JSON解析的时候经常用到的,这里不作进一步解释,看看峥老师说的用runtime字典转模型的方式。

没搞明白。。。

先用KVC吧。

 

总的来说,即便咱们知道了runtime是怎么用的,但是没有合适的环境使用runtime,也是白搭。所以,咱们现在能做的就是先了解runtime,随时记在心中,以后哪里能够用到的,可以尝试着用runtime的特性和上述几个方法来实现,甚至于用runtime解决bug。

另外这里有很多关于runtime的集合,大家可以参考:runtime专题

文/和珏猫(简书作者)
原文链接:http://www.jianshu.com/p/4fd0ef1a144b
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

时间: 2024-10-12 02:53:15

Runtime-b的相关文章

Runtime-字典转模型KVC实现

// // NSObject+Model.m // 05-runtime(字典转模型KVC实现) // // Created by kun on 16/8/17. // Copyright © 2016年 kun. All rights reserved. // #import "NSObject+Model.h" #import <objc/message.h> @implementation NSObject (Model) + (instancetype)modelW

iOS Runtime-OC黑魔法

在项目中经常会发现一些奇怪的功能.不太能找的到代码的出处,但却实现了功能,很可能这是实用了运行时的东西. 运行时即Runtime .使用起来很有意思.多了解也有助于对oc的理解. 这里我有写个关于Runtime 的demo     https://github.com/WangFeiF/WFRuntime 在这个博客里只是demo的摘要.详细可以下载demo.查看源码. // // ViewController.m // Runtime // // Created by 王飞 on 16/5/8

魅力 .NET:从 Mono、.NET Core 说起

转自:http://kb.cnblogs.com/page/514268/ 前段时间,被问了这样一个问题:.NET 应用程序是怎么运行的? 当时大概愣了好久,好像也没说出个所以然,得到的回复是:这是 .NET 程序员最基本的...呵呵! 微软开源,其实不只是对 .NET 本身有利,从另一方面讲,对于 .NET 程序员来说,因为开源,你可以想了解到你想要的任何事.在之前的岁月,你可以“平凡”做一个默默无闻的 C# 代码撰写者,可以不用考虑任何事,使用宇宙最强大的 IDE - Visual Stud

魅力 .NET:从 Mono、.NET Core[转]

前段时间,被问了这样一个问题:.NET 应用程序是怎么运行的? 当时大概愣了好久,好像也没说出个所以然,得到的回复是:这是 .NET 程序员最基本的...呵呵! 微软开源,其实不只是对 .NET 本身有利,从另一方面讲,对于 .NET 程序员来说,因为开源,你可以想了解到你想要的任何事.在之前的岁月,你可以“平凡”做一个默默无闻的 C# 代码撰写者,可以不用考虑任何事,使用宇宙最强大的 IDE - Visual Studio 编写代码后,发布到 IIS 即可,就是这么简单,甚至你不需要知道 II

刨根问底Objective-C Runtime

http://chun.tips/blog/2014/11/05/bao-gen-wen-di-objective%5Bnil%5Dc-runtime-(2)%5Bnil%5D-object-and-class-and-meta-class/ 刨根问底Objective-C Runtime(1)- Self & Super 刨根问底Objective-C Runtime(2)- Object & Class & Meta Class 刨根问底Objective-C Runtime(

刨根问底Objective-C Runtime(2)- Object &amp; Class &amp; Meta Class

Chun Tips 专注iOS开发 刨根问底Objective-C Runtime(2)- Object & Class & Meta Class 上一篇笔记讲述了objc runtime中Self 和 Super的细节,本篇笔记主要是讲述objc runtime中关于Object & Class & Meta Class的细节. 习题内容 下面代码的运行结果是? @interface Sark : NSObject @end @implementation Sark @e

刨根问底Objective-C Runtime(1)- Self &amp; Super

刨根问底Objective-C Runtime(1)- Self & Super - Chun Tips Chun Tips 专注iOS开发 刨根问底Objective-C Runtime(1)- Self & Super 前言 关于Objective-C Runtime一篇好的文档 : Understanding the Objective-C Runtime 译文地址为: http://blog.cocoabit.com/blog/2014/10/06/yi-li-jieobjecti

Runtime of Objective-C 2-理解oc中的类和对象

1: 类Class:       typedef struct objc_class * Class;     从Class的定义可以看出,它是一个 objc_class 结构类型的指针,objc_class又是什么呢? struct objc_class { struct objc_class* isa; struct objc_class* super_class; //root的为null const char* name; long version; long info; long in

刨根问底Objective-C Runtime(4)- 成员变量与属性

http://chun.tips/blog/2014/11/08/bao-gen-wen-di-objective[nil]c-runtime(4)[nil]-cheng-yuan-bian-liang-yu-shu-xing/ 上一篇笔记讲述了objc runtime中消息和Category的细节,本篇笔记主要是讲述objc runtime的 成员变量和属性. 习题内容 下面代码会? Compile Error / Runtime Crash / NSLog…? @interface Sark