美文网首页RunTime
iOS开发之RunTime上手入门

iOS开发之RunTime上手入门

作者: jiongjiongwang | 来源:发表于2016-08-09 22:47 被阅读28次

         众所周知,Objective-C是iOS开发的第一语言(虽然最近两年Swift发展迅猛,在最近的TIOBE编程语言排行榜上Swift的排名已经超过了Objective-C,但是现在iOS主流应用依然还是用Objective-C完成的)。Objective-C有一个可以称之为杀手级的语言特征----动态性,而OC的动态性最主要依赖的就是运行时系统(RunTime)。

          很多人在刚接触OC的运行时系统(RunTime)时,觉得它很深奥,因为它用到了C语言的API,毕竟很多的iOS程序员的C语言水平并不是很强,甚至到了看到C语言就恐惧的地步。因此在这里我通过几个简单的案例来阐述RunTime机制的强大之处,算是一个小小的入门了。

          1-最简单的运行时系统应用:根据字符串来调用内存中的一个类。

          这是运行时机制最常见也是最简单的应用了,它简单到甚至不用在项目中写入#import 

    <objc/runtime.h>用来导入runtime库。它根据传入的字符串来获取内存中存在的类。

    其代码如下:

    //1-根据字符串返回一个类

    Class cls =NSClassFromString(@"Person");

    //2-根据类来创建对象

    id person = [[cls alloc]init];

    //3-给person的属性赋值

    [person performSelector:@selector(setName:)withObject:@"wang"];

    //4-返回person的name属性值(使用KVC返回属性值)

    NSLog(@"person的name是%@",[person valueForKey:@"name"]);

    //5-调用person的eat方法

    if([person respondsToSelector:@selector(Eat)])

    {

    [person performSelector:@selector(Eat)withObject:nil];

    }

    else

    {

    NSLog(@"person不存在的方法");

    }

       2- 在程序运行时动态地添加一个类

         当需要在程序运行时动态地添加一个新的类到内存中时,我们需要用到C语言的API,需要导入runtime库,此时动态生成的类就会存在于内存中。

    代码如下:

    #import <objc/runtime.h>

    //1-设置类名(类名是常量)

    const char*className ="Dog";

    //2-根据类名获取类

    Class cls =objc_getClass(className);

    //3-判断类存不存在

    if(!cls)

    {

    //4-如果类不存在于当前的内存下,则需要重新根据类名来创建这个类

    //4-1设置运行时类的父类

    Class superClass = [NSObject class];

    //4-2在运行时下创建类

    cls =objc_allocateClassPair(superClass, className, 0);

    //5-判断类存不存在

    if(!cls)

    {

    NSLog(@"Dog类不存在");

    return;

    }

    else

    {

    //此时动态创建的Dog类存在于内存中

    NSLog(@"Dog类存在");

    }

    //6-在内存中注册类!!!!

    #warning在内存中注册类,一定要加!!!!!

    objc_registerClassPair(cls);

    }

    else

    {

    //类存在说明在当前的内存中已经存在了这个类(包括一些UIKit的系统类等)

    NSLog(@"类已经存在");

    }

        通过代码可以看出来,一股浓浓的C语言代码风格袭来,在内存中根据类名获取类还有在运行时创建一个新的类都用到了C语言的函数。

         3- 运行时给内存中的类添加新的方法

         此时也需要添加C语言的API,需要导入runtime库,代码如下:

    -(void)RunTime3withClassName:(NSString*) className

    {

    //1-获取内存中相关的类

    Class cls =NSClassFromString(className);

    if(!cls)

    {

    NSLog(@"%@类不存在",className);

    return;

    }

    else

    {

    NSLog(@"%@类存在",className);

    }

    //2-添加方法的实现(使用block实现,在block内传入方法参数)

    IMP myImp =imp_implementationWithBlock(^(id_self,NSString*str){

    NSLog(@"Hello %@",str);

    });

    class_addMethod(cls,@selector(sayHello:), myImp,"v@:@");

    //3-判断有没有添加方法成功

    id person = [[cls alloc]init];

    if([person respondsToSelector:@selector(sayHello:)])

    {

    [person performSelector:@selector(sayHello:)withObject:@"World"];

    }

    else

    {

    NSLog(@"当前的方法不存在");

    }

    }

    相关文章

      网友评论

        本文标题:iOS开发之RunTime上手入门

        本文链接:https://www.haomeiwen.com/subject/ajvdsttx.html