写点文章防忘记,好回忆!
Runtime到底有啥作用呐,传闻是江湖中的装B利器,可能用不到,但是你要会装B,不会装B的人生有啥意思?
Runtime是基于纯C语言的API,ObjectiveC就是C+Runtime。我们平时编写的OC代码,在程序运行过程中,最终都是转化成了runtime的C语言代码,它是OC幕后工作者。OC正是由于有了runtime才使得c语言具有了面向对象的能力,在程序的运行时刻,创建,检查,修改类、对象以及类、对象的方法。
RunTime的几个用法:
1)替换系统方法,
2)获得某个类的所有成员方法、所有成员变量
3)动态添加方法
4)为分类添加属性(亦为关联对象)
5)归档和解档
6)字典转model
7)万能控制器跳转
1>.替换系统方法
主要的使用场景,例如,我们在使用系统方法的同时,想看下log或者在系统方法里针对版本做判断
#import "UIImage+Extension.h"
#import@implementation UIImage (Extension)
+(void)load
{
Method method1 = class_getClassMethod([UIImage class], @selector(xl_imageWithName:));
Method method2 = class_getClassMethod([UIImage class], @selector(imageNamed:));
method_exchangeImplementations(method1, method2);
}
+ (UIImage *)xl_imageWithName:(NSString *)name
{
NSString *imageName = nil;
if (__IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_8_0) {
imageName = [NSString stringWithFormat:@"%@_7",name];
}else{
imageName = name;
NSLog(@"名字--%@",imageName);
}
UIImage *image = [UIImage xl_imageWithName:imageName];
return image;
}
@end
还有一个比较常见的使用场景,根据不同的屏幕显示不同的字体大小,结合这个问题我们来探讨一下,RunTime的黑魔法真的那么有用高效吗?
#import "UIFont+SizeByScreen.h"
#import <objc/runtime.h>
#define kScreen [UIScreen mainScreen].bounds.size.width
#define iPHONE6_SCREEN 375
@implementation UIFont (SizeByScreen)
+(void)load
{
Method method1 = class_getClassMethod(self, @selector(systemFontOfSize:));
Method method2 = class_getClassMethod(self, @selector(xl_systemFontOfSize:));
method_exchangeImplementations(method2, method1);
}
+ (UIFont *)xl_systemFontOfSize:(CGFloat)fontSize
{
UIFont *font;
if (kScreen < iPHONE6_SCREEN) {
font = [UIFont xl_systemFontOfSize:fontSize];
}else{
NSLog(@"我是大屏");
font = [UIFont xl_systemFontOfSize:fontSize * 1.2];
}
return font;
}
//不用黑魔法
+ (UIFont *)xlFontOfSize:(CGFloat)fontSize
{
UIFont *font;
if (kScreen < iPHONE6_SCREEN) {
font = [UIFont xl_systemFontOfSize:fontSize];
}else{
NSLog(@"我是大屏");
font = [UIFont xl_systemFontOfSize:fontSize * 1.2];
}
return font;
}
@end
如上,用了两种方式实现了不同屏幕字体大小显示的控制,从代码量来说,不用runtime的黑魔法似乎还少点,但是团队开发的时候,你想你的队友是直接用系统方法还是你命名的新方法?或者后期,代码维护,版本迭代的时候,如果你去熟悉新的代码,你想说啥?其实很多项目不到一年就死掉了,但是...把代码写到极致,是不是会有不一样的码生呐?
2>获得某个类的所有成员方法、所有成员变量
看到这个有没有赶紧去想,这个我能干啥用?学以致用,不能用于实战,我学他干啥,陶冶情操吗?学这个要是没用的话,出门看看天空都比这有价值?可能你不同意我的观点,但是我告诉你,这是真的
```思考结束,上代码
创建的一个对象
@interface XLPerson : NSObject
@property(nonatomic,strong)NSString *name;
@property(nonatomic,assign) int age;
@property(nonatomic,strong)NSString *birthday;
@end
// xlCount,存储对象属性数量,class_copyPropertyList会自动给xlCount赋值
unsigned int xlCount = 0;
objc_property_t *properties = class_copyPropertyList([XLPerson class], &xlCount);
/** 属性名字 */
for (int i =0; i < xlCount; i ++) {
//获得
objc_property_t property = properties[i];
const char *name = property_getName(property);
NSString *key = [NSString stringWithUTF8String:name];
NSLog(@"%d-----%@",i,key);
},
看下log,老铁们
2017-06-30 15:40:15.006 RunTimeStudy[14378:261232] 0-----name
2017-06-30 15:40:15.006 RunTimeStudy[14378:261232] 1-----age
2017-06-30 15:40:15.006 RunTimeStudy[14378:261232] 2-----birthday
还有一个:
unsigned int count = 0;
/** Ivar:表示成员变量类型 */
Ivar *ivars = class_copyIvarList([XLPerson class], &count);//获得一个指向该类成员变量的指针
for (int i =0; i < count; i ++) {
//获得Ivar
Ivar ivar = ivars[i]; //根据ivar获得其成员变量的名称--->C语言的字符串
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
NSLog(@"%d----%@",i,key);
}
2017-06-30 15:40:15.005 RunTimeStudy[14378:261232] 0----_age
2017-06-30 15:40:15.005 RunTimeStudy[14378:261232] 1----_name
2017-06-30 15:40:15.006 RunTimeStudy[14378:261232] 2----_birthday
结合项目开发,有啥用呐?自己研究技术有啥用呐?
例如常见的json转model是否用的到?那么json转model,value值出现nil null 情况如何处理,json里面嵌套array,dic如何解决?不了解的可以先看下yymodel,MJExtension等第三方库是如何实现的,后面会分析.我们不是农夫山泉,坚决不做搬运工.