• IOS高级开发 runtime(一)


    一、 简介

    IOS 开发中灵活使用runtime 会提高我们的程序性能和开发速度。要想使用runtime,首先要引入系统的头文件。

    <span style="font-size:18px;">#import <objc/runtime.h>
    </span>

    当我接触一样新的知识的时候,我比较喜欢先查看一下头文件,看看头文件里给我们提供了哪些接口。由于篇幅限制,我就偷个懒不往这里粘贴代码了大笑。当我们查看runtime.h的时候,我们会发现,其实runtime是很有条理的。头文件主要给我们提供了4个类型(当然不止4种大笑)的函数供我们使用。这4个类型分别以class、 method 、ivar、 objc加下划线开头。例如:

    <span style="font-size:14px;">const char *object_getClassName(id obj)//获取对象的类名</span>
    <span style="font-size:14px;">Ivar *class_copyIvarList(Class cls, unsigned int *outCount)//获取类的变量列表</span>
    <span style="font-size:12px;"><span style="font-family: Menlo; color: rgb(4, 51, 255);">unsigned</span><span style="font-family: Menlo;"> </span><span style="font-family: Menlo; color: rgb(4, 51, 255);">int</span><span style="font-family: Menlo;"> method_getNumberOfArguments(</span><span style="font-family: Menlo; color: rgb(52, 149, 175);">Method</span><span style="font-family: Menlo;"> m)//获取函数变量的个数</span></span>
    <p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"></p><p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;"><span style="color: rgb(4, 51, 255);">void</span> objc_setAssociatedObject(<span style="color: rgb(4, 51, 255);">id</span> object, <span style="color: rgb(4, 51, 255);">const</span> <span style="color: rgb(4, 51, 255);">void</span> *key, <span style="color: rgb(4, 51, 255);">id</span> value, <span style="color: rgb(52, 149, 175);">objc_AssociationPolicy</span> policy)//建立关联</span></p>


    二、runtime 大招


         2.1)为已有的类添加属性

    OC语法允许我们通过继承或者添加分类(category)修改(也不能说修改,就是改造成我们需要的类)已有的类。继承在这里不是我们想讨论的,主要是想说一下分类。分类可以允许我们添加属性(不会生成get和set方法,需要手动添加)和方法,但是却不允许我们添加成员变量。但是有些时候,我们需要添加一个变量来扩充这个类,比如:我有一个类Person类,带有age 和name 属性

    #import <Foundation/Foundation.h>
    
    @interface DZLPerson : NSObject
    
    @property(nonatomic,weak)NSString *name;
    @property(nonatomic,assign)NSInteger age;
    
    @end

    但是,后来我们发现,仅仅这两个属性是不够描述的,我们还需要添加一个job属性来描述一个人。因此我们想到了用分类来添加属性。

    <span style="font-size:14px;">#import "DZLPerson.h"
    
    @interface DZLPerson (Job)
    
    @property(nonatomic,copy)NSString* job;
    
    @end</span><span style="font-size:18px;">
    </span>

     但是事情往往没有那么简单,当我们运行程序时就会发现,程序崩溃了。

    <span style="font-size:14px;">- (void)viewDidLoad
    {
        [super viewDidLoad];
        DZLPerson *p=[[DZLPerson alloc] init];
        p.age=25;
        p.name=@"皮拉夫大王";
        p.job=@"ios";
        
        NSLog(@"%@",p);
    
    }</span>
    <span style="font-size:14px;">2015-04-10 00:05:50.591 runtime讲解[4197:209347] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[DZLPerson setJob:]: unrecognized selector sent to instance 0x7fe809f24790'</span>

    程序提示我们:找不到setJob方法。这是理所当然的,因为系统不能为我们自动添加成员变量了,也就不知道该如何帮我们创建setter 和getter方法了。但是我们可以通过runtime来添加属性,使我们能够像真正的修改了Person类那样使用新的属性job。

    首先在分类的.m 中导入runtime头文件,然后重写job的getter 和setter 方法。

    <span style="font-size:14px;">#import "DZLPerson+Job.h"
    #import <objc/runtime.h>
    
    
    static NSString *key=@"dzl"; //利用静态变量地址唯一不变的特性
    
    @implementation DZLPerson (Job)
    
    -(void)setJob:(NSString *)job
    {
    
        objc_setAssociatedObject(self, &key, job, OBJC_ASSOCIATION_COPY);
    }
    
    -(NSString *)job
    {
        return objc_getAssociatedObject(self, &key);
    }
    
    @end</span>

     

     建立关联引用,将这个对象和我们所利用的唯一不变的地址进行关联,而关联则是job属性,这样的话由于建立关联的对象存在,所进行关联的键唯一,所以我们的属性也被唯一保存了,如同保存在对象自身上一样。如图所示:

    通过关联引用我们就添加上了job 属性(叫属性有点不准确,如果可以的话我还是愿意叫它伪成员变量)。








       


  • 相关阅读:
    npm ci命令比npm installer命令快2至10倍
    Liferay 7.1发布啦
    2016/07/05 zend optimizer
    2016/06/16 phpexcel
    2016/06/13 phpexcel 未完待续
    2016/06/10 日历插件 Datepicker
    2016/06/09 ThinkPHP3.2.3使用分页
    2016/06/02 网摘记录 svn 服务器端 客户端 安装使用
    2016/05/27 php上传文件常见问题总结
    2016/05/25 抽象类与API(接口)差别
  • 原文地址:https://www.cnblogs.com/dengzhuli/p/4415557.html
Copyright © 2020-2023  润新知