iOS Runtime <一>

写点文章防忘记,好回忆!   

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

#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等第三方库是如何实现的,后面会分析.我们不是农夫山泉,坚决不做搬运工.

你可能感兴趣的:(iOS Runtime <一>)