runtime的黑魔法

要说明runtime,首先要明白objc这门语言,是基于C的封装.真是因为runtime,objc才有了面对对象的特性.

也就说,所有objc的语言,在运行时都会转换成C.

 

也是基于这样的特性,runtime可以做很多不可思议的事情.比如动态添加成员变量,函数等等.

 

User *usr = [[User alloc] init];
    
    NSLog(@"%@",usr.description);
    
    unsigned int count = 0;
    
    Ivar *members = class_copyIvarList([User class] , &count);
    
    
    for (int i = 0; i<count ; i++) {
        
        Ivar var = members[i];
        
        const char *memName = ivar_getName(var);
        
        const char *memType = ivar_getTypeEncoding(var);
        
        NSLog(@"%s type:%s", memName, memType);
        
    }
    
    //值修改
    Ivar name = members[0];
    
    object_setIvar(usr, name, @"王三蛋");
    
    NSLog(@"object_setIvar修改成员变量Name后的值:%@",usr.description);
    
    
    class_addMethod([User class], @selector(method:), (IMP)addingFunc, "i@:i@"); //通过class_addMethod 动态添加函数
    
    
    unsigned int FuncCount = 0;
    
    Method *membersFuncs = class_copyMethodList([User class], &FuncCount);
    
    //遍历已有函数名
    for (int i = 0 ; i< FuncCount; i++) {
        
        SEL Met = method_getName(membersFuncs[i]);
        
        NSString *MetName = [NSString stringWithCString:sel_getName(Met) encoding:NSUTF8StringEncoding];
        
        
        NSLog(@"User的函数:%@",MetName);
        
    }
    
    
    objc_msgSend(usr,@selector(method:),@"动态添加的函数");
int addingFunc(id self,SEL _cmd,NSString *str)
{
    NSLog(@"Added Func,%@",str);
    
    return 10;
}

 给出一个model转换的

//
//  NSObject+ModelHandle.h
//  MVVM
//
//  Created by M on 16/3/3.
//  Copyright © 2016年 Meng. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSObject (ModelHandle)

+(instancetype)ModelWithDict:(NSDictionary*)dict;

@end
//
//  NSObject+ModelHandle.m
//  MVVM
//
//  Created by M on 16/3/3.
//  Copyright © 2016年 Meng. All rights reserved.
//

#import "NSObject+ModelHandle.h"
#import <objc/runtime.h>

@implementation NSObject (ModelHandle)



+(instancetype)ModelWithDict:(NSDictionary*)dict
{
    id obj = [self new];
    
    
    for (NSString *propertyName in [self GetProperList]) {
        
        if (dict[propertyName]) {
            
            [obj setValue:dict[propertyName] forKey:propertyName];
            
        }
        
    }
    
    return obj;
}


+(NSArray*)GetProperList
{
    unsigned int count = 0;
    
    objc_property_t *propertyList = class_copyPropertyList([self class], &count);//获取class里的属性.
    
    NSMutableArray *arr = [NSMutableArray array];
    
    for (int i = 0 ; i<count; i++) {
        
        objc_property_t property = propertyList[i];
        
        const char *CharName = property_getName(property);
        
        NSString *StrName = [[NSString alloc] initWithUTF8String:CharName];
        
        [arr addObject:StrName];
        
    }
    
    free(propertyList);//释放
    
    return arr.copy;
}





@end

 

直接在相应的model的头文件里引入 #import "NSObject+ModelHandle.h"

Model *m = [Model  ModelWithDict:Dict[@"result"]];

 

相比 setValuesForKeysWithDictionary, 此函数对数据的检查不是那么严格.

posted @ 2016-02-18 14:23  NGI.  阅读(213)  评论(0编辑  收藏  举报
GitHub | M1989