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,"v@:");这个方法的时候,第三个参数前面并没有添加“(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
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
Runtime-b的更多相关文章
- 魅力 .NET:从 Mono、.NET Core 说起
前段时间,被问了这样一个问题:.NET 应用程序是怎么运行的? 当时大概愣了好久,好像也没说出个所以然,得到的回复是:这是 .NET 程序员最基本的...呵呵! 微软开源,其实不只是对 .NET 本身 ...
- .NET:从 Mono、.NET Core 说起
魅力 .NET:从 Mono..NET Core 说起 前段时间,被问了这样一个问题:.NET 应用程序是怎么运行的? 当时大概愣了好久,好像也没说出个所以然,得到的回复是:这是 .NET 程序员最基 ...
- 魅力 .NET:从 Mono、.NET Core[转]
前段时间,被问了这样一个问题:.NET 应用程序是怎么运行的? 当时大概愣了好久,好像也没说出个所以然,得到的回复是:这是 .NET 程序员最基本的...呵呵! 微软开源,其实不只是对 .NET 本身 ...
- Ant + ivy的安装
有了Ivy的帮忙,我们不需要为了一个库依赖管理而舍弃Ant去学那个难搞的Maven了. 基本配置步骤如下: 1.copy Ivy插件到ant_home/lib下: ivy安装 简单的安装方法: 直 ...
- 刨根问底Objective-C Runtime
http://chun.tips/blog/2014/11/05/bao-gen-wen-di-objective%5Bnil%5Dc-runtime-(2)%5Bnil%5D-object-and- ...
- ArcGIS Runtime SDK for iOS开发地图图层-图形图层
注:本文翻译自:https://developers.arcgis.com/ios/objective-c/guide/creating-a-graphics-layer.htm 创建图 ...
- 刨根问底Objective-C Runtime(4)- 成员变量与属性
http://chun.tips/blog/2014/11/08/bao-gen-wen-di-objective[nil]c-runtime(4)[nil]-cheng-yuan-bian-lian ...
- Objective-O Runtime 运行时初体验
Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一 ...
- 【腾讯Bugly干货分享】移动App入侵与逆向破解技术-iOS篇
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e0acc896e9ebb6865f321 如果您有耐心看完这篇文章,您将懂 ...
随机推荐
- 设置myeclipse自动生成的author等注释
一.window->preference->java->code styple->code Template 当你选择到这部的时候就会看见右侧有一个框显示出code这个选 ...
- rails + mongoid 使用
1. 测试环境 2. 创建工程 rails new mongoid_app --skip-active-record --skip-test-unit --skip-bundle 3. 修改gemfi ...
- 了解node.js
转载自http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb 当我向人们介绍nod ...
- windows7 'telnet'不是内部或外部命令--转载
['telnet'不是内部或外部命令,也不是可运行的程序或批处理文件]当你想用telnet命令时,发现提示这句话怎么办?其实很简单,接下来为大家介绍下如何使用 方法/步骤 一般只有windows7 ...
- vi 快捷键
屏幕翻滚类命令Ctrl+u:向文件首翻半屏Ctrl+d:向文件尾翻半屏Ctrl+f:向文件尾翻一屏Ctrl+b:向文件首翻一屏 shift+g:到尾部 H:跳到第一行.M:跳到中间.L:跳到最后一行. ...
- hdu2007
import java.util.*;class Main{public static void main(String args[]){Scanner cin=new Scanner(System. ...
- CentOS 6.7 final编译安装Python 2.7.11
CentOS 6.7默认的Python版本为2.6.6,现升级为Python 2.7.11 1.安装编译环境 yum groupinstall "Development tools" ...
- SCIP读书笔记(1)
这书也算是必修吧,尤其是我这种非科班人员,还是应该抽时间尽量学习一下.大致翻过一遍,习题非常多,尽力吧. ##构造过程抽象 * 为了表述认知,每种语言都提供了三种机制:基本元素:组合方式:抽象方法. ...
- 3G/4G网卡使用
整体架构: pppd call option & ----------↓---------- option脚本(设置PPP连接) ----------↓---------- chat脚本(进行 ...
- HDFS的Java客户端操作代码(HDFS删除文件或目录)
1.HDFS删除文件或目录 package Hdfs; import java.io.IOException; import java.net.URI; import org.apache.hadoo ...