iOS 高级开发 runtime(三)_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > iOS 高级开发 runtime(三)

iOS 高级开发 runtime(三)

 2015/4/14 10:22:53  皮拉夫大王  程序员俱乐部  我要评论(0)
  • 摘要:三、动态添加方法我们可以通过runtime动态地添加方法。那么到底啥叫动态添加方法呢?动态添加方法就是当我们程序运行时才知道我们应该调用哪个方法。我们首先需要了解这一点,当我们编写完一段代码后,我们点击run的时候,编译器会先进行预编译、编译、链接、运行这几个步骤。C语言是再编译的时候就已经确定了函数的调用顺序,而OC在编译的时候,只是确定了哪个对象,发送什么消息,具体这个消息能不能找到对应的方法还不知道,只有在运行时,才能确定是否能够执行我们所期望的方法。我们以下面的代码为例
  • 标签:iOS 开发

三 、动态添加方法

       我们可以通过runtime动态地添加方法。那么到底啥叫动态添加方法呢?动态添加方法就是当我们程序运行时才知道我们应该调用哪个方法。我们首先需要了解这一点,当我们编写完一段代码后,我们点击run 的时候,编译器会先进行预编译、编译、链接、运行这几个步骤。C语言是再编译的时候就已经确定了函数的调用顺序,而OC在编译的时候,只是确定了哪个对象,发送什么消息,具体这个消息能不能找到对应的方法还不知道,只有在运行时,才能确定是否能够执行我们所期望的方法。我们以下面的代码为例:

 

class="objc">    [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执行了


      说明我们动态添加方法成功了。最后特别提示哦,如果函数和方法不是一回事,不要把他俩搞混了。方法是通过类或者对象调用的,而函数是可以直接调用执行的。

 

发表评论
用户名: 匿名