什么是runtime?

runtime是一套纯c的API.平时用oc写的代码在运行时都会先转成runtime代码,然后在执行。

runtime可以干什么?

1.交换方法。(method_exchangeImplementations)

首先创建一个People类,有俩个类方法,+(void)run{NSLog@"跑"}和+(void)sing{NSLog@"唱歌"}.

依次调用这两个方法,控制台会依次输出 跑 和 唱歌 。

用runtime获取到People类的run方法。

Method m1=class_getClassMethod([People class], @selector(run)) ;

同理获取sing方法。

Method m2=class_getClassMethod([People class], @selector(sing)) ;

交换两个方法。

method_exchangeImplementations(m1, m2) ;

在依次调用这个两个方法,控制台会输出 唱歌 和 跑。

实例方法用 class_getInstanceMethod 来获取。

2.在分类中设置属性。

众所周知,在分类中是无法添加实例变量的。就算在分类中声明了一个属性,也只是生成了这个属性的set方法和get方法,并不会生成这个属性。并且,虽然打点调用会有

提示,但是一旦运行程序就会崩溃。所以要想在分类中添加实例变量还得使用runtime来操作。

使用到的是

  void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy) 这个方法。

其中:

object就是你想要添加属性的对象。

key则是你想保存的属性的键。

value则是你想保存的属性的值。

policy则是你想保存的属性的属性(assign,copy之类的)。

比如在一个分类中声明了一个属性。

@property(nonatomic,copy)NSString* name

在其set方法中这么调用:

char nameKey ;//声明属性的键。

-(void)setName:(NSString *)name

{

objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC) ;//关联 键和值

}

在其get方法中这么调用来获取这个属性:

-(NSString* )name

{

return objc_getAssociatedObject(self, &nameKey) ;

}

这样就在分类中添加了一个属性。

3.获取一个类的所有属性。

-(void)getPropertyFromPeople

{

unsigned int outcount ;

Ivar* ivars=class_copyIvarList([People class],&outcount) ;//会返回属性的个数,outcount即为总个数

for(int i=0;i<outcount;i++)

{

Ivar ivar=ivars[i] ;

const char* name=ivar_getName(ivar) ;

const char* type=ivar_getTypeEncoding(ivar) ;

NSLog(@"属性名称%s 类型%s",name,type) ;

}

free(ivars) ;//注意释放内存

}

4.将dict转换成model类。

将方法写在NSObject的分类中,然后model类继承于NSObject,在导入分类的头文件。

-(instancetype)modelWithDictionary:(NSDictionary* )dict

{

Class modelClass=self.class ;

while (modelClass&&modelClass!=[NSObject class]) {

unsigned int count=0 ;

Ivar* ivars=class_copyIvarList(modelClass, &count) ;

for (int i=0; i<count; i++) {

Ivar ivar=ivars[i] ;

NSString* key=[NSString stringWithUTF8String:ivar_getName(ivar)] ;

key=[key substringFromIndex:1] ;

id value=dict[key] ;

if (value==nil) {

continue ;

}

NSString* type=[NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)] ;

//type的格式为@“@\“NSString\””

NSRange range=[type rangeOfString:@"@"] ;

if (range.location!=NSNotFound) {

if (![type containsString:@"NS"]) {

//是自定义的类型

Class another=NSClassFromString([type substringWithRange:NSMakeRange(2, type.length-3)]) ;

value=[another secondModelWithDictionary:value] ;

}else if([[type substringWithRange:NSMakeRange(2, type.length-3)] isEqualToString:@"NSArray"])

{

//包含数组

//包含model数据的数组

NSArray* array=(NSArray* )value ;

NSMutableArray* modelArr=[NSMutableArray array] ;

//用于接收数组中model的类型

id class ;

if ([self respondsToSelector:@selector(classStringByArray)]) {

class=[self classStringByArray] ;

for (int i=0; i<array.count; i++) {

//将数组的数据转换成model添加到临时数组中

[modelArr addObject:[class secondModelWithDictionary:array[i]]] ;

}

value=modelArr ;

}

}

}

[self setValue:value forKey:key] ;

}

free(ivars) ;

modelClass=[modelClass superclass] ;

}

return self ;

}

+(instancetype)secondModelWithDictionary:(NSDictionary* )dict

{

NSObject* object=[[self alloc]init] ;

[object modelWithDictionary:dict] ;

return object ;

}

Runtime初学习的更多相关文章

  1. clisp, scheme 和 clojure 初学习

    clisp, scheme和clojure 初学习 1 clojure "clojure绝对会成为你的编程工具箱里的终极武器" "其他语言可能只是工具,但 Clojure ...

  2. c# window服务-初学习

    window服务-初学习 一.工具: VS2015+NET Framework4.5. 二.操作: 1.新建windows服务的项目: 2.修改windows服务相关内容: 3.预览windows服务 ...

  3. Python初学习:简单的练习题

    Python初学习 一些见到那的练习题: 初级难度 设计一重量转换器,输入以g为单位的数字后,返回换算结果以Kg为单位的结果 中级难度 设计一个求直角三角形斜边长的函数,(以两个直角边为参数,求最长边 ...

  4. iOS runtime 初步学习

    注: 在Xocde5之后, 使用运行时方法需要进行2步设置1. 在Build Setting中搜索'msg', 设置'Strict Checking' 为 NO2. 使用需要导入头文件 #import ...

  5. runtime 初入

    一.runtime简介 RunTime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C语言,函数的调用在编译的时候会决定调用哪个函数. 对于OC的函数,属于 ...

  6. Swift初学习

    距离swift发布10天了,也简单看了一下swift的语法,个人感觉相对于object-c很是简单明了.Swift的出现并不能说明iOS开发简单了很多,有可能会变得复杂,你需要学习两门编程语言,因为在 ...

  7. Jquery 插件初学习

    参考文章:插件开发精品教程,让你的jQuery提升一个台阶 刚刚学了一下jquery的插件插件开发,写个demo记录.练习一下.毕竟,输出才是最好的学习. 这个也不过是最基础的一个插件写法,只是,自己 ...

  8. requests库写接口测试框架初学习

    学习网址:    https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dscpm/ff75b907-415d-4220-89 ...

  9. 2018.2.21 Python 初学习

    折腾了一天,一直在用CMD学习Python写Hello World.偶然间发现可以用Pycharm.也算是给后面想学习的人提个醒,方便省事许多. format()使用方法. age = 20name ...

随机推荐

  1. CSS盒子模型与box-sizing

    今天在学习的时候偶然看到一张图片: 我瞬间瞪大了眼睛:width和height竟然不包括padding和border!! 过去所学知识有问题!在我的印象里,width应该是包含padding和bord ...

  2. 关于print和echo的区别

    我的想法是print是函数,echo是语句.有一个点很难去说明就是为什么可以执行print 666.可以这样不加括号,象print(666);至于为什么一定要认为print是函数,而非网上说的语句和函 ...

  3. java byte&0xFF

    做串口端口通讯时,数据都是以byte类型发送的 普通的byte范围是-128-127,而java的byte范围是0-255 因此将数据的byte转成java的byte时,需要与0xff(1111111 ...

  4. 使用VS2010在Coding.net上进行代码托管

    网上有VS2010和Github结合使用办法,但是Github在国内使用太慢,本文使用相同的配置方法稍作改动让VS2010代码托管在coding.net平台上.由于只是稍做记录让自己不会遗忘,所以叙述 ...

  5. petapoco存储过程

    db.ExecuteScalar<string>("exec P_GetCode @0,@1,@2,@3,@4,@5",); using (var db = new D ...

  6. ubuntu 13.10 svn工具 rabbitvcs 安装

    ubuntu 版本:13.10:桌面模式默认:unity :文件管理器:nautilus

  7. bottlepy template

    bottle template usage 1 example 使用bottle模板,最简单的方法是使用template函数或view装饰器 1.1 template 函数 例子如下: from bo ...

  8. review again and again

    盲评结果出来了.然而对于我并没有太大的影响.从头到尾我没有紧张过,自然也不会有如释重负的感觉. 昨天说了事情要提前做准备.早上,到教研室挺早,review的时候,发现论文中一个关于目录的小问题,解决掉 ...

  9. 软件调试——CPU异常列表

    CPU异常主要分为三类:错误类异常,陷阱类异常和终止类异常 1 错误类异常 Fault CPU遇到该类异常后,会先将CS和EIP(当前发生错误的指令,而不是下一条指令)压栈,然后跳到异常处理函数中,执 ...

  10. python中的内存管理

    不像大多数编译型语言,变量必须在使用之前声明名字和类型,在python中,变量在第一次被赋值时自动声明.在变量创建时,python解释器会根据语法和右侧的操作数来决定新对象的类型,在对象创建后,一个该 ...