一.Runtime的使用
1.runtime:
指一个程序在运行(或者在被执行)的状态。也就是说,当你打开一个程序使它在电脑上运行的时候,那个程序就是处于运行时刻。在一些编程语言中,把某些可以重用的程序或者实例打包或者重建成为“运行库"。这些实例可以在它们运行的时候被连接或者被任何程序调用。
2.objective-c中runtime:
是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。 在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码。
3.runtime在编程中使用的场景
1> 给分类添加属性,使用objc_setAssociatedObjectC函数给分类添加属性:
***分类默认不能添加属性。如果要添加属性,必须重新属性的 setter & getter 方法
利用运行时机制给分类添加属性 runTimer
-(void)setCurrentURLString:(NSString *)currentURLString {
objc_setAssociatedObject(self, HMURLKey,currentURLString, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString*)currentURLString {
return objc_getAssociatedObject(self,HMURLKey);
}
2> 动态交换两个方法的实现
此处实现通过交换方法实现自定义打印方法
下面还实现了打印NSArray和NSDictionary的方法,可以将存放在集合中的内容以UTF_8的形式打印出来
@implementation NSObject(Log)
+ (void)load {
// 交换两个方法的实现
method_exchangeImplementations(class_getInstanceMethod([NSObjectclass], @selector(description)), class_getInstanceMethod([NSObject class],@selector(Description)));
}
/**
* 该方法是用来自定义模型(直接继承NSObject)的输出格式
*
* @return 格式化后的字符串
*/
- (NSString *)Description{
Class class = [self class];
NSMutableString *resultStr = [NSMutableString stringWithFormat:@"%@= {\n",[self pkxDescription]];
while (class != [NSObject class]) {
// 0.如果是UIResponder或CALayer的子类,就使用系统的默认输出格式
if ([[class description]hasPrefix:@"NS"] || [[class description] hasPrefix:@"__"]||[[class description] hasPrefix:@"AV"] || [[class description]hasPrefix:@"_UIFlowLayout"] || [[class description]hasPrefix:@"UITouchesEvent"] || [class isSubclassOfClass:[UIResponderclass]] || [class isSubclassOfClass:[CALayer class]] || [classisSubclassOfClass:[UIImage class]])return [self Description];
unsigned int count = 0;
// 1.获取类成员变量列表,count为类成员变量数量
Ivar *vars = class_copyIvarList(class,&count);
for (int index = 0; index < count;index ++) {
// 2.根据索引获得指定位置的成员变量
Ivar var = vars[index];
// 3.获得成员变量名
const char *name =ivar_getName(var);
// 4.成员变量名转化成oc字符串
NSString *varName = [NSStringstringWithUTF8String:name];
// 5.获得成员变量对应的值
id value = [selfvalueForKey:varName];
[resultStr appendFormat:@"\t%@= %@;\n", varName, value];
}
// 6.释放指针
free(vars);
// 7.获得父类
class = class_getSuperclass(class);
}
[resultStr appendString:@"}\n"];
return resultStr;
}
@end
@implementation NSArray(Log)
- (NSString *)descriptionWithLocale:(id)locale{
NSMutableString *strM = [NSMutableStringstringWithString:@"(\n"];
[self enumerateObjectsUsingBlock:^(id obj,NSUInteger idx, BOOL *stop) {
[strMappendFormat:@"\t%@,\n", obj];
}];
[strM appendString:@")"];
return strM;
}
@end
@implementation NSDictionary(Log)
- (NSString*)descriptionWithLocale:(id)locale {
NSMutableString *strM = [NSMutableStringstringWithString:@"{\n"];
[selfenumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[strM appendFormat:@"\t%@ =%@;\n", key, obj];
}];
[strM appendString:@"}\n"];
return strM;
}
3> 获得某一个类所有属性
获取一个类的所有属性后,可以通过KVC实现对类的属性值的改变:
• object-c的遍历一个类的所有属性的实现方法:
/**
* 获得当前类的所有属性
*/
+ (NSArray *)properties {
NSMutableArray *pArray = [NSMutableArrayarray];
unsigned int count = 0;
// 获得指定类的所有属性
objc_property_t *properties =class_copyPropertyList([self class], &count);
// unsigned char *ch = {'A','b'};
// 遍历属性
for(int index = 0; index < count; ++index) {
// 根据索引获得对应的属性
objc_property_t property =properties[index];
// 获得属性名字
const char *cname =property_getName(property);
// 将c语言字符串转换为oc字符串
NSString *ocname = [[NSString alloc]initWithCString:cname encoding:NSUTF8StringEncoding];
[pArray addObject:ocname];
}
NSLog(@"pArray= %@",pArray);
return pArray;
}
• swift中实现遍历获取一个类的属性的方法实现
extension NSObject {
class func printIvars() {
// 运行时.获取类里面的 _成员变量
// outCount:UnsafeMutablePointer<UInt32>: UInt32类型的可变
var outCount: UInt32 = 0 // _成员变量的数量
// ivars实际上是一个数组
let ivars = class_copyIvarList(self,&outCount)
// 获取里面的每个元素
for i in 0..<outCount {
// ivar是一个结构体的指针
let ivar = ivars[Int(i)]
// 获取 _成员变量的名称
let cName = ivar_getName(ivar) // cNamec语言的字符串,首元素的地址
let name = String(CString: cName,encoding: NSUTF8StringEncoding)
print("name: \(name)")
}
// 需要释放
free(ivars)
}
}
附:
以上是runtime在项目中最近常使用的地方,不过runtime的核心是对底层的掌握,所以如果想要对runtime有更深入的了解可访问下面网站
• 这里http://www.opensource.apple.com/source/objc4/可以下到苹果维护的开源代码
• 苹果官方文档https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html 里有详细的Runtime函数文档。