Runtime基本使用

一.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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值