利用runtime为系统类追加属性、成员变量

来源:互联网 发布:淘宝修改运费模板 编辑:程序博客网 时间:2024/05/21 17:05

首先,第一个问题,
1》runtime实现的机制是什么,怎么用,一般用于干嘛?

runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者

比如说,下面一个创建对象的方法 :

[[MJPerson alloc] init]
runtime :objc_msgSend(objc_msgSend(“MJPerson” , “alloc”), “init”)

第二个问题
runtime 用来干什么呢??用在那些地方呢?怎么用呢?
runtime是属于OC的底层, 可以进行一些非常底层的操作(用OC是无法现实的, 不好实现)

在程序运行过程中, 动态创建一个类(比如KVO的底层实现)在程序运行过程中, 动态地为某个类添加属性\方法, 修改属性值\方法遍历一个类的所有成员变量(属性)\所有方法例如:我们需要对一个类的属性进行归档解档的时候属性特别的多,这时候,我们就会写很多对应的代码,但是如果使用了runtime就可以动态设置! 例如,PYPerson.h的文件如下所示
@interface PYPerson : NSObject@property (nonatomic, assign) int age;@property (nonatomic, assign) int height;@property (nonatomic, copy) NSString *name;@property (nonatomic, assign) int age2;@property (nonatomic, assign) int height2;@property (nonatomic, assign) int age3;@property (nonatomic, assign) int height3;@property (nonatomic, assign) int age4;@property (nonatomic, assign) int height4;@end 

而PYPerson.m实现文件的内容如下

#import "PYPerson.h"@implementation PYPerson    (void)encodeWithCoder:(NSCoder )encoder    {    unsigned int count = 0;    Ivar ivars = class_copyIvarList([PYPerson class], &count);    for (int i = 0; i<count; i++) {    // 取出i位置对应的成员变量    Ivar ivar = ivars[i];    // 查看成员变量    const char *name = ivar_getName(ivar);    // 归档    NSString *key = [NSString stringWithUTF8String:name];    id value = [self valueForKey:key];    [encoder encodeObject:value forKey:key];    }    free(ivars);    }    (id)initWithCoder:(NSCoder *)decoder    {    if (self = [super init]) {    unsigned int count = 0;    Ivar *ivars = class_copyIvarList([PYPerson class], &count);    for (int i = 0; i<count; i++) {        // 取出i位置对应的成员变量        Ivar ivar = ivars[i];        // 查看成员变量        const char *name = ivar_getName(ivar);        // 归档        NSString *key = [NSString stringWithUTF8String:name];        id value = [decoder decodeObjectForKey:key];        // 设置到成员变量身上        [self setValue:value forKey:key];    }    free(ivars);    }    return self;    }@end 

这样我们可以看到归档和解档的案例其实是runtime写下的

学习,runtime机制首先要了解下面几个问题
1.相关的头文件和函数
a> 头文件

利用头文件,我们可以查看到runtime中的各个方法!

b> 相关应用

NSCoding(归档和解档, 利用runtime遍历模型对象的所有属性)字典 –> 模型 (利用runtime遍历模型对象的所有属性, 根据属性名从字典中取出对应的值, 设置到模型的属性上)KVO(利用runtime动态产生一个类)用于封装框架(想怎么改就怎么改)这就是我们runtime机制的只要运用方向

c> 相关函数

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

2.必备常识
a> Ivar : 成员变量
b> Method : 成员方法
从上面例子中我们看到我们定义的成员变量,如果要是动态创建方法,可以使用Method。

================== 调皮的分割线 ==================
@"这层讲主题的内容:利用runtime为系统类追加属性成员变量

我们的“射鸡湿”呢,设计了如下的cell :(图图图)
这里写图片描述
放眼望去,敌军寥寥几人,消灭掉他们不费吹灰之力,长得像极了系统的那个叫做 UITableViewCellStyleSubtitle 的cellStyle,只是多了右下角那组奇怪的东东,可你又懒得自定义一个cell,不是么?于是你想:能不能给系统的UITableViewCell添加2个属性成员变量啊,这样就可以很好的实现效果了啦~~ (嘤嘤嘤)。

嗯,可以。下面就开始撸runtime & category代码(什么?还不会category?活该单身汪,汪汪汪!)

首先,CMD+N 创建新文件,这里要创建category(图如下:)
这里写图片描述 Next
这里写图片描述 现在会建category了吧!
然后.h文件就是酱紫:

#import <UIKit/UIKit.h>@interface UITableViewCell (RightDownPlugin)//下面两个控件就是敌军的弱点,加上去他们就GG了@property (nonatomic,strong) UIImageView *statusImgV; //状态图@property (nonatomic,strong) UILabel *statusLab; //状态label@end

然后.m就是酱紫了:

#import "UITableViewCell+RightDownPlugin.h"#include <objc/runtime.h>@implementation UITableViewCell (RightDownPlugin)//定义常量 必须是C语言字符串 因为runtime是C语言API,你写其他的语言它不认识啦~~static char *statusImgKey = "statusImgKey";static char *statusLabKey = "statusLabKey";/*  【科普时间 后面会用到】    OBJC_ASSOCIATION_ASSIGN;            //assign策略    OBJC_ASSOCIATION_COPY_NONATOMIC;    //copy策略    OBJC_ASSOCIATION_RETAIN_NONATOMIC;  // retain策略    OBJC_ASSOCIATION_RETAIN;    OBJC_ASSOCIATION_COPY;     */ /*       id object 给哪个对象的属性赋值       const void *key 属性对应的key       id value  设置属性值为value       objc_AssociationPolicy policy  使用的策略,是一个枚举值,和copy,retain,assign是一样的,手机开发一般都选择NONATOMIC       objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);     */// 然后就需要自定义set和get方法了,因为category默认是不能添加属性的,哈哈哈 以前是加了也没用,现在是加了会报错。- (void)setStatusImgV:(UIImageView *)statusImgV{    objc_setAssociatedObject(self,statusImgKey,statusImgV,OBJC_ASSOCIATION_RETAIN);}- (UIImageView *)statusImgV{    return objc_getAssociatedObject(self, statusImgKey);}// Lab- (void)setStatusLab:(UILabel *)statusLab{    objc_setAssociatedObject(self,statusLabKey,statusLab,OBJC_ASSOCIATION_RETAIN);}- (UILabel *)statusLab{    return objc_getAssociatedObject(self, statusLabKey);}@end

【多么华丽的走位,多了漂亮的击杀,嗯?亲爱的观众朋友们,我就想问一句:还有谁?哈哈哈哈 】 ——逗比小智

1 0