欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS 开发 Runtime 运行时机制 完全解读

程序员文章站 2022-06-03 08:16:11
前言 在最开始听到runtime的时候,我是感到恐惧的,多么高大上的东西啊!!!后来,开始在网上查一些资料,可是就是只有那么几篇,看了好久,还不知所云,所以就更加恐惧了!!!!后来经过查看docum...

前言

在最开始听到runtime的时候,我是感到恐惧的,多么高大上的东西啊!!!后来,开始在网上查一些资料,可是就是只有那么几篇,看了好久,还不知所云,所以就更加恐惧了!!!!后来经过查看documents 以及一些国外大牛的blogs,终于对runtime有了更深刻的了解!

runtime实现的机制是什么

runtime是一套比较底层的纯c语言api, 属于1个c语言库, 包含了很多底层的c语言api。 在我们平时编写的oc代码中, 程序运行过程时, 其实最终都是转成了runtime的c语言代码, runtime算是oc的幕后工作者 比如说,下面一个创建对象的方法中.
举例: oc : [[mjperson alloc] init] 
runtime : objc_msgsend(objc_msgsend("mjperson" , "alloc"), "init")

runtime 用来干什么呢??用在那些地方呢?怎么用呢?

runtime用来干什么?

runtime是属于oc的底层, 可以进行一些非常底层的操作(用oc是无法现实的, 不好实现)

在程序运行过程中, 动态创建一个类(比如kvo的底层实现) 在程序运行过程中, 动态地为某个类添加属性\方法, 修改属性值\方法 遍历一个类的所有成员变量(属性)\所有方法 例如:我们需要对一个类的属性进行归档解档的时候属性特别的多,这时候,我们就会写很多对应的代码,但是如果使用了runtime就可以动态设置!

runtime用在哪些地方? 怎么用?
应用案例:

#import 
给分类添加属性
// 运行时给分类添加属性--get方法
- (uiview *)backgroundview {
    return objc_getassociatedobject(self, &backgroundviewkey);
}

// 运行时给分类添加属性--set方法
- (void)setbackgroundview:(uiview *)backgroundview {
    objc_setassociatedobject(self, &backgroundviewkey, backgroundview, objc_association_retain_nonatomic);
}
方法交换(黑魔法)
    method imagenamedmethod = class_getclassmethod(self, @selector(imagenamed:));
    // 获取xmg_imagenamed
    method xmg_imagenamedmethod = class_getclassmethod(self, @selector(xmg_imagenamed:));

    // 交互方法:runtime
    method_exchangeimplementations(imagenamedmethod, xmg_imagenamedmethod);
获取对象属性/私有属性
jdgtextfield *phonenumeber = [[jdgtextfield alloc] init];
    phonenumeber.placeholder = @"请输入手机号";
    [phonenumeber setvalue:[uicolor colorwithred:246.0/255 green:222.0/255 blue:186.0/255 alpha:1.0] forkeypath:@"_placeholderlabel.textcolor"];
字典转模型(kvc)
[self setvaluesforkeyswithdictionary:dict];
kvc 动态获取属性–下拉刷新
self.tableview addobserver:self forkeypath:@"contentoffset" options:nskeyvalueobservingoptionnew context:nil];
归档解档
1)nsdata-归档2个person对象到同一文件中

归档(编码)

// 新建一块可变数据区
nsmutabledata *data = [nsmutabledata data];
// 将数据区连接到一个nskeyedarchiver对象
nskeyedarchiver *archiver = [[[nskeyedarchiver alloc] initforwritingwithmutabledata:data] autorelease];
// 开始存档对象,存档的数据都会存储到nsmutabledata中
[archiver encodeobject:person1 forkey:@"person1"];
[archiver encodeobject:person2 forkey:@"person2"];
// 存档完毕(一定要调用这个方法)
[archiver finishencoding];
// 将存档的数据写入文件
[data writetofile:path atomically:yes];

2)nsdata-从同一文件中恢复2个person对象

恢复(解码)

// 从文件中读取数据
nsdata *data = [nsdata datawithcontentsoffile:path];
// 根据数据,解析成一个nskeyedunarchiver对象
nskeyedunarchiver *unarchiver = [[nskeyedunarchiver alloc] initforreadingwithdata:data];
person *person1 = [unarchiver decodeobjectforkey:@"person1"];
person *person2 = [unarchiver decodeobjectforkey:@"person2"];
// 恢复完毕
[unarchiver finishdecoding];
nsclassfromstring
nsstring *vcname = obj[jdgrootvcname];
        class vcclass = nsclassfromstring(vcname);
        uiviewcontroller *vc = [[vcclass alloc] init];
block

runtime相关函数

objc_msgsend : 给对象发送消息
class_copymethodlist : 遍历某个类所有的方法
class_copyivarlist : 遍历某个类所有的成员变量
class_..... 这是我们学习runtime必须知道的函数!

runtime原理机制

—未完待续