iOS 高级开发 runtime(三)
三 、动态添加方法
我们可以通过runtime动态地添加方法。那么到底啥叫动态添加方法呢?动态添加方法就是当我们程序运行时才知道我们应该调用哪个方法。我们首先需要了解这一点,当我们编写完一段代码后,我们点击run 的时候,编译器会先进行预编译、编译、链接、运行这几个步骤。C语言是再编译的时候就已经确定了函数的调用顺序,而OC在编译的时候,只是确定了哪个对象,发送什么消息,具体这个消息能不能找到对应的方法还不知道,只有在运行时,才能确定是否能够执行我们所期望的方法。我们以下面的代码为例:
[person test_inPerson];
// objc_msgSend(person, @selector(test_inPerson));上面的语句再编译后得到的就是这个函数。 // 通过编译我们能够知道三点:1、消息的接受者是person对象。2、需要执行名字为test_inPerson 的方法 3、这个方法不带参数
在上一篇博客中,我提到了SEL和IMP,但是由于写博客时已经太晚了,就没有认真地解释。
如果想了解方法调用的过程,恐怕我们需要了解4个概念:(1)isa 指针。( 2)superclass 属性 。 (3)SEL 。 ( 4)IMP。
1) isa 指针:指向对象的类的指针。
2)superclass :指向父类。
3)SEL :选择器,是根据方法名字生成的ID, 每个selector其实是一个char*类型,记录对应IMP的位置。SEL列表本身是一个哈希存储的set集合,查找起来非常高效。
4) IMP:函数指针。
下面我们就来说一下方法调用的过程。
/*
调用方法
*/
[person test_inPerson]; /*
转换成消息 objc_msgSend(person, @selector(test_inPerson));上面的语句再编译后得到的就是这个函数。
*/ /*
1)检查 是否selector 2)检查person 是否为空,如果为空的话就把selector也置为空,这样的话相当于什么也不做,当然也不报错 3)根据SEL 查找IMP。首先从缓存中查找,看看缓存中是否存在SEL对应的IMP。如果存在则执行,否则继续下一步。 4)根据SEL 和 isa 指针再IMP 列表中查找对应的IMP。如果找到则执行,否则执行下一步。 5)根据superclass 和SEL 查找父类的IMP 如果找到则执行。否则继续执行这一步,直到NSObject 类。 6)如果再NSObject类中仍然找不到方法,则会报错,找不到方法。
*/
了解了方法调用的过程,下面我们就来看看如何动态的添加方法。为了能够表达清楚,特在此敬上代码
DZLPerson *person=[[DZLPerson alloc] init]; //发送消息想要执行名字为test0的方法,但是我们person类及其分类中并没有该方法的实现
[person performSelector:@selector(test0)];
#import "DZLPerson.h"
#import <objc/runtime.h> @implementation DZLPerson /*
注意 这是函数 不是方法。函数是不能通过方法调用的。
*/
void test0()
{
NSLog(@"test0 执行了");
} /*
如果找不到类方法则调用该方法,决定是否动态地添加方法
*/
//+(BOOL)resolveClassMethod:(SEL)sel
//{
// return BOOL;
//} /*
如果找不到实例方法则调用该方法,决定是否动态地添加方法
*/
+(BOOL)resolveInstanceMethod:(SEL)sel
{ // 如果找不到的方法时test0 的话
if ([NSStringFromSelector(sel) isEqualToString:@"test0"])
{ //添加方法。其实就是将现有的函数实现(IMP) 和 SEL进行连接。
class_addMethod(self,sel,test0,"v@:");
} return YES;
} @end
打印结果为
2015-04-13 22:43:06.406 runtime讲解[12452:693059] test0执行了
说明我们动态添加方法成功了。最后特别提示哦,如果函数和方法不是一回事,不要把他俩搞混了。方法是通过类或者对象调用的,而函数是可以直接调用执行的。
iOS 高级开发 runtime(三)的更多相关文章
- IOS高级开发 runtime(一)
一. 简介 IOS 开发中灵活使用runtime 会提高我们的程序性能和开发速度.要想使用runtime,首先要引入系统的头文件. <span style="font-size:18p ...
- IOS 高级开发 runtime(二)
二.移魂大法 使用runtime还可以交换两个函数.先贴上代码和执行结果. #import <Foundation/Foundation.h> @interface DZLPerson : ...
- (转发)IOS高级开发~Runtime(三)
11.系统类的方法实现部分替换 - (void) methodExchange { Method m1 = class_getInstanceMethod([NSStringclass],@selec ...
- (转发)IOS高级开发~Runtime(四)
用C代替OC: #import <objc/runtime.h> #import <objc/message.h> #import <stdio.h> extern ...
- (转发)IOS高级开发~Runtime(二)
一些公用类: @interface ClassCustomClass :NSObject{ NSString *varTest1; NSString *varTest2; NSString *varT ...
- (转发)IOS高级开发~Runtime(一)
IOS高级开发-Runtime(一) IOS高级开发-Runtime(二) IOS高级开发-Runtime(三) IOS高级开发-Runtime(四) 一些公用类: @interface Custom ...
- IOS高级开发之多线程(四)NSOperation
1.什么是NSOperation,NSOperationQueue? NSOperation是一个抽象的基类,表示一个独立的计算单元,可以为子类提供有用且线程安全的建立状态,优先级,依赖和取消等操作. ...
- ios高级开发之多线程(三)GCD技术
GCD是基于C的API,它是libdispatch的的市场名称.而libdispatch作为Apple公司的一个库,为并发代码在多核硬件(跑IOS或者OS X)上执行提供有力支持. 那么我们为什么要用 ...
- IOS高级开发~Runtime(一)
#import <Foundation/Foundation.h> @interface CustomClass : NSObject -(void)fun1; @end @interfa ...
随机推荐
- Eclipse 卸载插件
直奔主题,不罗嗦! 1.help 2.about eclipse 3. 点击Installation Details 4.选中你安装的插件点击Uninstall... 5.从新启动,OK.
- Bzoj 1562: [NOI2009]变换序列 匈牙利算法,二分图匹配
题目: http://cojs.tk/cogs/problem/problem.php?pid=409 409. [NOI2009]变换序列 ★★☆ 输入文件:transform.in 输出文 ...
- 集成电路中的assert和deassert应该如何翻译?
转载自:http://m.blog.csdn.net/blog/code_robot/37663085 我每次看到电路中的assert与deassert时,总是感觉别扭,因为词典翻译总是"断 ...
- Android强制设置横屏或竖屏
全屏 在Activity的onCreate方法中的setContentView(myview)调用之前添加下面代码 requestWindowFeature(Window.FEATURE_NO_TIT ...
- 由.Net类库提供的农历计算(C#农历)-获取当前日期的农历日期
; i <= chineseDate.GetMonthsInYear(DateTime.Now.Year); i++) { Console.W ...
- Centos下安装FTP并进行虚拟用户访问方式配置
1. 安装认证所需包 [root@localhost]#yum install pam* [root@localhost]#yum install db4* 首先安装PAM(用于用户认证)和DB4(用 ...
- linux+nginx+tomcat负载均衡,实现session同步
linux+nginx+tomcat负载均衡,实现session同步 花了一个上午的时间研究nginx+tomcat的负载均衡测试,集群环境搭建比较顺利,但是session同步的问题折腾了几个小时才搞 ...
- spring mvc Spring Data Redis RedisTemplate [转]
http://maven.springframework.org/release/org/springframework/data/spring-data-redis/(spring-data包下载) ...
- 非spring环境中配置文件工具
http://commons.apache.org/proper/commons-configuration/ 注意:属性的值使用","分割,会造成读取属性值不正确的问题.建议使用 ...
- HTTP请求类型详解
HTTP(HyperText Transfer Protocol)是一套计算机通过网络进行通信的规则.计算机专家设计出HTTP,使HTTP客户(如Web浏览器)能够从HTTP服务器(Web服务 器)请 ...