• IOS开发 模型赋值 runtime


    #import "CZJsonObject.h"
    #import <objC/runtime.h>
    #import <objc/message.h>
    
    
    NSString *setter_from_key(NSString *key)
    {
        //capitalise the first letter
        NSString *setter = [key stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[key substringToIndex:1] uppercaseString]];
        //add 'set' and the colon
        setter = [NSString stringWithFormat:@"set%@:", setter];
        return setter;
    }
    
    @implementation CZJsonObject
    
    - (void)fitNilInproperty
    {
        Class _targetClass = [self class];
        while ([_targetClass class]!=[NSObject class]) {
            [self fitNibWithClass:_targetClass];
            _targetClass = [_targetClass superclass];
        }
    }
    /*
     * @waring 对于自定义getter和/或setter方法名的属性无效
     */
    - (void)fitNibWithClass:(Class)class
    {
        //传出参数,获取属性的数量
        unsigned int outCount = 0;
        //获取属性列表的副本(所指向的指针)
        objc_property_t* ptable  = class_copyPropertyList(class, &outCount);//执行后outCount等于类的属性数量
        //备份列表指针,便于最后释放
        objc_property_t* ptable_first = ptable;
        //遍历属性列表
        for (unsigned int index = 0; index<outCount; index++) {
            //获取 当前属性的@encode
            const char* attrName = property_getAttributes(*ptable);
            NSString* attrNameStr = [NSString stringWithCString:attrName encoding:NSUTF8StringEncoding];
            //判断当前属性类型是否为对象
            //若@encode以@T开头,则为id型(近似但不等于对象)
            //若@encode以@T开头,而且匹配[".+"],则意味着属性为自定义对象类型(NS类包含在内)
            if (([attrNameStr hasPrefix:@"T@"]) && ([attrNameStr rangeOfString:@"".+"" options:NSRegularExpressionSearch].location!=NSNotFound)) {
                //获取当前属性 的 属性名
                const char* propertyCName = property_getName(*ptable);
                NSString* propertyName = [NSString stringWithCString:propertyCName encoding:NSUTF8StringEncoding];
                //获取getter的方法名
                NSString* getterName = propertyName;
                //检查该getter是否存在,若getter被自定义,则getter名不等于属性名
                BOOL isDefaultGetter = [self respondsToSelector:NSSelectorFromString(getterName)];
                if (isDefaultGetter) {
                    //调用该属性的getter,获取属性值
                    NSObject* propertyValue = [self performSelector:NSSelectorFromString(getterName)];
                    //当属性值为nil

               if (propertyValue==nil||propertyValue==[NSNull null]||propertyValue==NULL) {

                        //从@encode分离类型信息

                        NSArray* attrArr = [attrNameStr componentsSeparatedByString:@"""];

                        //取出属性类型名

                        NSString* propertyTypeClassName = [attrArr objectAtIndex:1];

                        //根据类型名获取默认值

                        NSObject* defaultValue = [self defaultValueWithClassType:propertyTypeClassName];

                        //同上,检查该getter是否为默认的setter

                        BOOL isDefaultSetter = [self respondsToSelector:NSSelectorFromString(setter_from_key(propertyName))];

                        if (isDefaultSetter) {

                            //调用setter,将默认值传人

                            [self performSelector:NSSelectorFromString(setter_from_key(propertyName)) withObject:defaultValue];

                        }

                    }

                }

            }

    
            //列表偏移到下一位属性
            ptable++;
        }
        //遍历完成后,释放属性列表副本
        free(ptable_first);
    }
    
    - (id)defaultValueWithClassType:(NSString*)type
    {
        id result = [[NSObject alloc]init];
        if ([type hasPrefix:@"NS"]) {
            if ([type isEqualToString:@"NSString"]) {
                result = @"";//[[NSString alloc]init];
            }else if ([type isEqualToString:@"NSNumber"]) {
                result = @0;//[[NSNumber alloc]init];
            }else if ([type isEqualToString:@"NSDictionary"]) {
                result = [[NSDictionary alloc]init];
            }else if ([type isEqualToString:@"NSArray"]) {
                result = [[NSArray alloc]init];
            }else if ([type isEqualToString:@"NSMutableDictionary"]) {
                result = [[NSMutableDictionary alloc]initWithCapacity:1];
            }else if ([type isEqualToString:@"NSMutableArray"]) {
                result = [[NSMutableArray alloc]initWithCapacity:1];
            }else if ([type isEqualToString:@"NSDate"]) {
                result = [[NSDate alloc]initWithTimeIntervalSince1970:0];
            }else if ([type isEqualToString:@"NSData"]) {
                result = [[NSData alloc]initWithBase64EncodedString:@" " options:NSDataBase64DecodingIgnoreUnknownCharacters];
            }
        }
        return result;
    }
    
    - (void)setValue:(id)value forUndefinedKey:(NSString *)key
    {
        if ([key isEqualToString:@"id"]) {
            _theId = value;
        }else if([key isEqualToString:@"description"]){
            _theDescription = value;
        }else{
            //NSLog(@"%@ underfine the property: @property(nonatomic,readwrite) %@ %@; = %@",[self class],[value class],key,value);
        }
    }
  • 相关阅读:
    [转]Ctags 使用细节
    [转]ctags的使用及相关参数介绍
    [转]ubuntu面板 图标缺失的处理办法
    压缩空气动力自行车
    丰富的开发体验和激动人心的用户体验:XAML
    发现一个控件,介绍一下
    智能电视的设想(发明畅想)
    裹脚布
    整理了《类库开发的设计准则》一文
    关于设计器类程序的模型,先记录下来,怕以后忘记了
  • 原文地址:https://www.cnblogs.com/mojiewei/p/5651373.html
Copyright © 2020-2023  润新知