Runtime基本使用

来源:互联网 发布:舞霸王跳舞软件 编辑:程序博客网 时间:2024/06/07 20:28

一.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函数文档。

0 0
原创粉丝点击