-
1.背景
- 由于OC是运行时语言,只有在程序运行时,才会去确定对象的类型,并调用类与对象相应的方法。利用runtime机制让我们可以在程序运行时动态修改类、对象中的所有属性、方法。
-
2.什么是运行时(Runtime)?
- 运行时是苹果提供的纯C语言的开发库(运行时是一种非常牛逼、开发中经常用到的底层技术)
-
3.运行时的作用?
- 能获得某个类的所有成员变量
- 能获得某个类的所有属性
- 能获得某个类的所有方法
- 交换方法实现
- 能动态添加一个成员变量
- 能动态添加一个属性
- 能动态添加一个方法
-
4.运行时的简单使用
- 运行时的一种很简单的使用方式,将字典对象转为模型。当然,你可能会问,我用KVO直接调用 setValuesForKeysWithDictionary:方法,传入一个字典一样可以快速将字典转模型啊,但是这种方法有它的弊端。只有遍历某个类(模型)中所有的成员变量,然后通过成员变量从字典中取出对应的值并赋值最为稳妥,否则,当模型中的属性数量与字典中的key的数量不一样时,就会报错。而且,由于runtime是更底层的语言,我们编写的OC代码在运行时,编译器内部会先转为C和C++的代码,然后再执行,因而运用runtime机制,程序的性能也会更好。下面就让我们简单的看看它的一个简单使用案例:
- (1)首先,我们定义一个工具类,并且定义一个方法来获取某个对象的成员属性并打印
#import "LSLRunTime.h"
//#import <objc/runtime.h>
// 或
#import <objc/message.h>
@implementation LSLRunTime
/**
* 利用运行时,遍历某个类所有的成员变量并打印
*
* @param objc 等待访问的对象
*/
+ (void)copyIvarListWithClassName:(id)objc
{
// 成员变量的数量
unsigned int outCount = 0;
// 获得所有的成员变量
Ivar *ivars = class_copyIvarList([objc class], &outCount);
// 遍历所有的成员变量
for (int i = 0; i<outCount; i++) {
// 取出i位置对应的成员变量
Ivar ivar = ivars[i];
// 获得成员变量的名字
const char *propertyName = ivar_getName(ivar);
// 获取变量编码类型
const char *propertyType = ivar_getTypeEncoding(ivar);
// 打印
NSLog(@"%@:%s--%s",objc, propertyName ,propertyType);
}
// 如果函数名中包含了copy\new\retain\create等字眼,那么这个函数返回的数据就需要手动释放
free(ivars);
}
@end
- (2)假如我们需要获取UITextField控件中所有属性,并修改它的某个属性的值
- 1)首先用运行时获取它的所有属性
#import "LSLRunTime.h"
// ....
// 用运行时输出对象的属性名称
[LSLRunTime copyIvarListWithClassName:[UITextField class]];
// ....
- 2)结果(部分结果)
// ....
--- UITextField:_leftViewOffset--{CGSize="width"d"height"d}
--- UITextField:_rightViewOffset--{CGSize="width"d"height"d}
--- UITextField:_backgroundView--@"UITextFieldBorderView"
--- UITextField:_disabledBackgroundView--@"UITextFieldBorderView"
--- UITextField:_systemBackgroundView--@"UITextFieldBackgroundView"
---
UITextField:_displayLabel
--@"UITextFieldLabel"
--- UITextField:_placeholderLabel--@"UITextFieldLabel"
--- UITextField:_suffixLabel--@"UITextFieldLabel"
--- UITextField:_prefixLabel--@"UITextFieldLabel"
--- UITextField:_iconView--@"UIImageView"
--- UITextField:_label--@"UILabel"
// ....
- 3)上面我们通过运行时获取了对象的属性名称和属性类型,下面则用KVC来修改对象的属性对应的值。比如修改UITextFiled文本框中的占位文字的默认颜色:
#import "LSLLoginRegisterTextFiled.h"
// 占位文字对应的属性名称
#define LSLPlaceholderColorKey @"placeholderLabel.textColor"
// 默认的占位文字颜色
#define LSLPlaceholderDefaultColor [UIColor grayColor]
// 聚焦的占位文字颜色
#define LSLPlaceholderFocusColor [UIColor whiteColor]
@interface LSLLoginRegisterTextFiled()<UITextFieldDelegate>
@end
@implementation LSLLoginRegisterTextFiled
- (void)awakeFromNib
{
// 设置文本框输入文字时的颜色
self.textColor = LSLPlaceholderFocusColor;
// 设置光标的颜色
self.tintColor = LSLPlaceholderFocusColor;
// 使用kvc,设置占位文字的默认颜色
[self setValue:LSLPlaceholderDefaultColor forKeyPath:LSLPlaceholderColorKey];
}
// ....
@end
参考博客:http://www.cnblogs.com/guoxiao/p/3583432.html 和
http://my.oschina.net/panyong/blog/297640