diff --git a/Benchmark/ModelBenchmark.xcodeproj/project.xcworkspace/xcuserdata/WHC.xcuserdatad/UserInterfaceState.xcuserstate b/Benchmark/ModelBenchmark.xcodeproj/project.xcworkspace/xcuserdata/WHC.xcuserdatad/UserInterfaceState.xcuserstate index 69386ed..5a290e6 100644 Binary files a/Benchmark/ModelBenchmark.xcodeproj/project.xcworkspace/xcuserdata/WHC.xcuserdatad/UserInterfaceState.xcuserstate and b/Benchmark/ModelBenchmark.xcodeproj/project.xcworkspace/xcuserdata/WHC.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Benchmark/ModelBenchmark.xcodeproj/xcuserdata/WHC.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Benchmark/ModelBenchmark.xcodeproj/xcuserdata/WHC.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 9d9aed5..c3747d8 100644 --- a/Benchmark/ModelBenchmark.xcodeproj/xcuserdata/WHC.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/Benchmark/ModelBenchmark.xcodeproj/xcuserdata/WHC.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -48,32 +48,16 @@ - - - - diff --git a/Benchmark/ModelBenchmark/Test.json b/Benchmark/ModelBenchmark/Test.json index bc15167..9e15b95 100644 --- a/Benchmark/ModelBenchmark/Test.json +++ b/Benchmark/ModelBenchmark/Test.json @@ -1,13 +1,53 @@ { - "status" : { - "msg" : "succ", - "code" : 0 - }, - "data" : [ - "吞天记", - "谢家皇后", - "乱世宏图", - "老婆是武林盟主" - ], - "token" : "" -} \ No newline at end of file + "status": { + "code": 0, + "msg": "succ" + }, + "num": 10, + "cur_page": 1, + "total_num": 1, + "total_page": 10, + "data": [ + { + "value": "3", + "key": "仙侠" + }, + { + "value": "3", + "key": "仙侠传人生路" + }, + { + "value": "3", + "key": "仙侠六界" + }, + { + "value": "3", + "key": "仙侠奇缘之凤千灵" + }, + { + "value": "3", + "key": "仙侠道" + }, + { + "value": "2", + "key": "仙侠一世之神果转世" + }, + { + "value": "2", + "key": "仙侠世界大冒险" + }, + { + "value": "2", + "key": "仙侠之命安彼生" + }, + { + "value": "2", + "key": "仙侠之路" + }, + { + "value": "2", + "key": "仙侠奇缘" + } + ], + "token": "" +} diff --git a/Benchmark/ModelBenchmark/ViewController.m b/Benchmark/ModelBenchmark/ViewController.m index f9fe170..45eefe8 100755 --- a/Benchmark/ModelBenchmark/ViewController.m +++ b/Benchmark/ModelBenchmark/ViewController.m @@ -42,10 +42,10 @@ - (void)viewDidLoad { NSData *data = [NSData dataWithContentsOfFile:path]; NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; - NSArray * testArray = [NSString whc_ModelWithJson:json keyPath:@"data"]; + NSArray * testArray = [NSDictionary whc_ModelWithJson:json keyPath:@"data"]; NSLog(@"test = %@",testArray); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - //[self benchmarkGithubUser]; + [self benchmarkGithubUser]; [self benchmarkWeiboStatus]; // [self testRobustness]; diff --git a/Benchmark/ModelBenchmark/WHC_Model/NSObject+WHC_Model.m b/Benchmark/ModelBenchmark/WHC_Model/NSObject+WHC_Model.m index 0d8e9f5..d6f520c 100644 --- a/Benchmark/ModelBenchmark/WHC_Model/NSObject+WHC_Model.m +++ b/Benchmark/ModelBenchmark/WHC_Model/NSObject+WHC_Model.m @@ -714,7 +714,7 @@ + (WHC_ModelPropertyInfo *)classExistProperty:(NSString *)property withObject:(N + (id)handleDataModelEngine:(id)object class:(Class)class { if(object) { if([object isKindOfClass:[NSDictionary class]]) { - NSObject * modelObject = [class new]; + __block NSObject * modelObject = nil; NSDictionary * dictionary = object; __block NSDictionary * replacePropertyNameMap = [class getModelReplacePropertyMapper]; __block NSDictionary * replacePropertyClassMap = [class getModelPropertyClassMapper]; @@ -724,160 +724,172 @@ + (id)handleDataModelEngine:(id)object class:(Class)class { replacePropertyNameMap = [class whc_ModelReplacePropertyMapper]; [class setModelReplacePropertyMapper:replacePropertyNameMap]; } - [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { - NSString * actualProperty = key; - id subObject = obj; - if (replacePropertyNameMap != nil) { - NSString * replaceName = replacePropertyNameMap[actualProperty]; - if (replaceName) { - actualProperty = replaceName; - } - } - WHC_ModelPropertyInfo * propertyInfo = [class getPropertyInfo:actualProperty]; - if (propertyInfo == nil) { - if (replacePropertyClassMap) { - propertyInfo = [WHC_ModelPropertyInfo new]; - [propertyInfo setClass:replacePropertyClassMap[actualProperty] valueClass:[obj class]]; - }else { - if ([class respondsToSelector:@selector(whc_ModelReplacePropertyClassMapper)]) { - [class setModelPropertyClassMapper:[class whc_ModelReplacePropertyClassMapper]]; - } - propertyInfo = [self classExistProperty:actualProperty withObject:modelObject valueClass:[obj class]]; - } - if (propertyInfo) { - [class setModelInfo:propertyInfo property:actualProperty]; + if ([class isSubclassOfClass:[NSDictionary class]]) { + modelObject = [NSMutableDictionary dictionary]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]]) { + [(NSMutableDictionary *)modelObject setObject:[self handleDataModelEngine:obj class:[obj class]] forKey:key]; }else { - return; + [(NSMutableDictionary *)modelObject setObject:obj forKey:key]; } - SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[actualProperty substringToIndex:1].uppercaseString, [actualProperty substringFromIndex:1]]); - if (![modelObject respondsToSelector:setter]) { - actualProperty = [self existproperty:actualProperty withObject:modelObject]; - if (actualProperty == nil) { - return; + }]; + }else { + modelObject = [class new]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { + NSString * actualProperty = key; + id subObject = obj; + if (replacePropertyNameMap != nil) { + NSString * replaceName = replacePropertyNameMap[actualProperty]; + if (replaceName) { + actualProperty = replaceName; } - setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[actualProperty substringToIndex:1].uppercaseString, [actualProperty substringFromIndex:1]]); } - propertyInfo->setter = setter; - } - switch (propertyInfo->type) { - case _Array: - if(![subObject isKindOfClass:[NSNull class]]){ - Class subModelClass = NULL; - if (replaceContainerElementClassMap) { - subModelClass = replaceContainerElementClassMap[actualProperty]; - }else if ([class respondsToSelector:@selector(whc_ModelReplaceContainerElementClassMapper)]) { - replaceContainerElementClassMap = [class whc_ModelReplaceContainerElementClassMapper]; - subModelClass = replaceContainerElementClassMap[actualProperty]; - [class setContainerElementClassMapper:replaceContainerElementClassMap]; - } - if (subModelClass == NULL) { - subModelClass = NSClassFromString(actualProperty); - if (subModelClass == nil) { - NSString * first = [actualProperty substringToIndex:1]; - NSString * other = [actualProperty substringFromIndex:1]; - subModelClass = NSClassFromString([NSString stringWithFormat:@"%@%@",[first uppercaseString],other]); - } + WHC_ModelPropertyInfo * propertyInfo = [class getPropertyInfo:actualProperty]; + if (propertyInfo == nil) { + if (replacePropertyClassMap) { + propertyInfo = [WHC_ModelPropertyInfo new]; + [propertyInfo setClass:replacePropertyClassMap[actualProperty] valueClass:[obj class]]; + }else { + if ([class respondsToSelector:@selector(whc_ModelReplacePropertyClassMapper)]) { + [class setModelPropertyClassMapper:[class whc_ModelReplacePropertyClassMapper]]; } - if (subModelClass) { - ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [self handleDataModelEngine:subObject class:subModelClass]); - }else { - ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + propertyInfo = [self classExistProperty:actualProperty withObject:modelObject valueClass:[obj class]]; + } + if (propertyInfo) { + [class setModelInfo:propertyInfo property:actualProperty]; + }else { + return; + } + SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[actualProperty substringToIndex:1].uppercaseString, [actualProperty substringFromIndex:1]]); + if (![modelObject respondsToSelector:setter]) { + actualProperty = [self existproperty:actualProperty withObject:modelObject]; + if (actualProperty == nil) { + return; } - - }else{ - ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @[]); + setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[actualProperty substringToIndex:1].uppercaseString, [actualProperty substringFromIndex:1]]); } - break; - case _Dictionary: - if(![subObject isKindOfClass:[NSNull class]]){ - Class subModelClass = NULL; - if (replaceContainerElementClassMap) { - subModelClass = replaceContainerElementClassMap[actualProperty]; - }else if ([class respondsToSelector:@selector(whc_ModelReplaceContainerElementClassMapper)]) { - replaceContainerElementClassMap = [class whc_ModelReplaceContainerElementClassMapper]; + propertyInfo->setter = setter; + } + switch (propertyInfo->type) { + case _Array: + if(![subObject isKindOfClass:[NSNull class]]){ + Class subModelClass = NULL; if (replaceContainerElementClassMap) { subModelClass = replaceContainerElementClassMap[actualProperty]; + }else if ([class respondsToSelector:@selector(whc_ModelReplaceContainerElementClassMapper)]) { + replaceContainerElementClassMap = [class whc_ModelReplaceContainerElementClassMapper]; + subModelClass = replaceContainerElementClassMap[actualProperty]; [class setContainerElementClassMapper:replaceContainerElementClassMap]; } + if (subModelClass == NULL) { + subModelClass = NSClassFromString(actualProperty); + if (subModelClass == nil) { + NSString * first = [actualProperty substringToIndex:1]; + NSString * other = [actualProperty substringFromIndex:1]; + subModelClass = NSClassFromString([NSString stringWithFormat:@"%@%@",[first uppercaseString],other]); + } + } + if (subModelClass) { + ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [self handleDataModelEngine:subObject class:subModelClass]); + }else { + ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + + }else{ + ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @[]); } - if (subModelClass == NULL) { - subModelClass = NSClassFromString(actualProperty); - if (subModelClass == nil) { - NSString * first = [actualProperty substringToIndex:1]; - NSString * other = [actualProperty substringFromIndex:1]; - subModelClass = NSClassFromString([NSString stringWithFormat:@"%@%@",[first uppercaseString],other]); + break; + case _Dictionary: + if(![subObject isKindOfClass:[NSNull class]]){ + Class subModelClass = NULL; + if (replaceContainerElementClassMap) { + subModelClass = replaceContainerElementClassMap[actualProperty]; + }else if ([class respondsToSelector:@selector(whc_ModelReplaceContainerElementClassMapper)]) { + replaceContainerElementClassMap = [class whc_ModelReplaceContainerElementClassMapper]; + if (replaceContainerElementClassMap) { + subModelClass = replaceContainerElementClassMap[actualProperty]; + [class setContainerElementClassMapper:replaceContainerElementClassMap]; + } + } + if (subModelClass == NULL) { + subModelClass = NSClassFromString(actualProperty); + if (subModelClass == nil) { + NSString * first = [actualProperty substringToIndex:1]; + NSString * other = [actualProperty substringFromIndex:1]; + subModelClass = NSClassFromString([NSString stringWithFormat:@"%@%@",[first uppercaseString],other]); + } } + if (subModelClass) { + NSMutableDictionary * subObjectDictionary = [NSMutableDictionary dictionary]; + [subObject enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { + [subObjectDictionary setObject:[self handleDataModelEngine:obj class:subModelClass] forKey:key]; + }]; + ((void (*)(id, SEL, NSDictionary *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObjectDictionary); + }else { + ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + + }else{ + ((void (*)(id, SEL, NSDictionary *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @{}); } - if (subModelClass) { - NSMutableDictionary * subObjectDictionary = [NSMutableDictionary dictionary]; - [subObject enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { - [subObjectDictionary setObject:[self handleDataModelEngine:obj class:subModelClass] forKey:key]; - }]; - ((void (*)(id, SEL, NSDictionary *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObjectDictionary); - }else { - ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + break; + case _String: + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSString *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + }else{ + ((void (*)(id, SEL, NSString *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @""); } - - }else{ - ((void (*)(id, SEL, NSDictionary *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @{}); - } - break; - case _String: - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSString *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); - }else{ - ((void (*)(id, SEL, NSString *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @""); - } - break; - case _Number: - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSNumber *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); - }else{ - ((void (*)(id, SEL, NSNumber *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @(0)); - } - break; - case _Integer: - ((void (*)(id, SEL, NSInteger))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject integerValue]); - break; - case _UInteger: - ((void (*)(id, SEL, NSUInteger))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject unsignedIntegerValue]); - break; - case _Boolean: - ((void (*)(id, SEL, BOOL))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject boolValue]); - break; - case _Float: - ((void (*)(id, SEL, float))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject floatValue]); - break; - case _Double: - ((void (*)(id, SEL, double))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject doubleValue]); - break; - case _Char: - ((void (*)(id, SEL, char))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject charValue]); - break; - case _Model: - ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [self handleDataModelEngine:subObject class:propertyInfo->class]); - break; - case _Date: - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSDate *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); - } - break; - case _Value: - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSValue *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); - } - break; - case _Data: { - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSData *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + break; + case _Number: + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSNumber *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + }else{ + ((void (*)(id, SEL, NSNumber *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @(0)); + } + break; + case _Integer: + ((void (*)(id, SEL, NSInteger))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject integerValue]); + break; + case _UInteger: + ((void (*)(id, SEL, NSUInteger))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject unsignedIntegerValue]); + break; + case _Boolean: + ((void (*)(id, SEL, BOOL))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject boolValue]); + break; + case _Float: + ((void (*)(id, SEL, float))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject floatValue]); + break; + case _Double: + ((void (*)(id, SEL, double))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject doubleValue]); + break; + case _Char: + ((void (*)(id, SEL, char))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject charValue]); + break; + case _Model: + ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [self handleDataModelEngine:subObject class:propertyInfo->class]); + break; + case _Date: + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSDate *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + break; + case _Value: + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSValue *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + break; + case _Data: { + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSData *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + break; } - break; + default: + + break; } - default: - - break; - } - }]; + }]; + } return modelObject; }else if ([object isKindOfClass:[NSArray class]]){ NSMutableArray * modelObjectArr = [NSMutableArray new]; diff --git a/README.md b/README.md index b8c414c..a314caf 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Time lost (Benchmark 1000 times) 集成 ============== * 使用CocoaPods: - - pod 'WHC_Model', '~> 1.6.2' + - pod 'WHC_Model', '~> 1.6.3' * 手工集成: - 导入文件夹WHC_ModelKit diff --git a/WHC_Model.podspec b/WHC_Model.podspec index 091f6e3..3a162d0 100755 --- a/WHC_Model.podspec +++ b/WHC_Model.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "WHC_Model" - s.version = "1.6.2" + s.version = "1.6.3" s.summary = "iOS平台高效转换引擎json->model,model->json,model->Dictionary,支持模型类继承其他模型类,支持指定路径转换,不区分json的key和模型属性名称大小写,自动处理json中null" s.homepage = "https://github.com/netyouli/WHC_Model" @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.platform = :ios s.platform = :ios, "6.0" - s.source = { :git => "https://github.com/netyouli/WHC_Model.git", :tag => "1.6.2"} + s.source = { :git => "https://github.com/netyouli/WHC_Model.git", :tag => "1.6.3"} s.source_files = "WHC_ModelKit/*.{h,m}" diff --git a/WHC_Model.xcodeproj/project.xcworkspace/xcuserdata/WHC.xcuserdatad/UserInterfaceState.xcuserstate b/WHC_Model.xcodeproj/project.xcworkspace/xcuserdata/WHC.xcuserdatad/UserInterfaceState.xcuserstate index bc3f855..74de8f3 100644 Binary files a/WHC_Model.xcodeproj/project.xcworkspace/xcuserdata/WHC.xcuserdatad/UserInterfaceState.xcuserstate and b/WHC_Model.xcodeproj/project.xcworkspace/xcuserdata/WHC.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/WHC_ModelKit/NSObject+WHC_Model.m b/WHC_ModelKit/NSObject+WHC_Model.m index 5611013..33afa7d 100644 --- a/WHC_ModelKit/NSObject+WHC_Model.m +++ b/WHC_ModelKit/NSObject+WHC_Model.m @@ -721,8 +721,8 @@ + (WHC_ModelPropertyInfo *)classExistProperty:(NSString *)property withObject:(N + (id)handleDataModelEngine:(id)object class:(Class)class { if(object) { - if([object isKindOfClass:[NSDictionary class]]){ - NSObject * modelObject = [class new]; + if([object isKindOfClass:[NSDictionary class]]) { + __block NSObject * modelObject = nil; NSDictionary * dictionary = object; __block NSDictionary * replacePropertyNameMap = [class getModelReplacePropertyMapper]; __block NSDictionary * replacePropertyClassMap = [class getModelPropertyClassMapper]; @@ -732,160 +732,172 @@ + (id)handleDataModelEngine:(id)object class:(Class)class { replacePropertyNameMap = [class whc_ModelReplacePropertyMapper]; [class setModelReplacePropertyMapper:replacePropertyNameMap]; } - [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { - NSString * actualProperty = key; - id subObject = obj; - if (replacePropertyNameMap != nil) { - NSString * replaceName = replacePropertyNameMap[actualProperty]; - if (replaceName) { - actualProperty = replaceName; - } - } - WHC_ModelPropertyInfo * propertyInfo = [class getPropertyInfo:actualProperty]; - if (propertyInfo == nil) { - if (replacePropertyClassMap) { - propertyInfo = [WHC_ModelPropertyInfo new]; - [propertyInfo setClass:replacePropertyClassMap[actualProperty] valueClass:[obj class]]; - }else { - if ([class respondsToSelector:@selector(whc_ModelReplacePropertyClassMapper)]) { - [class setModelPropertyClassMapper:[class whc_ModelReplacePropertyClassMapper]]; - } - propertyInfo = [self classExistProperty:actualProperty withObject:modelObject valueClass:[obj class]]; - } - if (propertyInfo) { - [class setModelInfo:propertyInfo property:actualProperty]; + if ([class isSubclassOfClass:[NSDictionary class]]) { + modelObject = [NSMutableDictionary dictionary]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]]) { + [(NSMutableDictionary *)modelObject setObject:[self handleDataModelEngine:obj class:[obj class]] forKey:key]; }else { - return; + [(NSMutableDictionary *)modelObject setObject:obj forKey:key]; } - SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[actualProperty substringToIndex:1].uppercaseString, [actualProperty substringFromIndex:1]]); - if (![modelObject respondsToSelector:setter]) { - actualProperty = [self existproperty:actualProperty withObject:modelObject]; - if (actualProperty == nil) { - return; + }]; + }else { + modelObject = [class new]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { + NSString * actualProperty = key; + id subObject = obj; + if (replacePropertyNameMap != nil) { + NSString * replaceName = replacePropertyNameMap[actualProperty]; + if (replaceName) { + actualProperty = replaceName; } - setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[actualProperty substringToIndex:1].uppercaseString, [actualProperty substringFromIndex:1]]); } - propertyInfo->setter = setter; - } - switch (propertyInfo->type) { - case _Array: - if(![subObject isKindOfClass:[NSNull class]]){ - Class subModelClass = NULL; - if (replaceContainerElementClassMap) { - subModelClass = replaceContainerElementClassMap[actualProperty]; - }else if ([class respondsToSelector:@selector(whc_ModelReplaceContainerElementClassMapper)]) { - replaceContainerElementClassMap = [class whc_ModelReplaceContainerElementClassMapper]; - subModelClass = replaceContainerElementClassMap[actualProperty]; - [class setContainerElementClassMapper:replaceContainerElementClassMap]; - } - if (subModelClass == NULL) { - subModelClass = NSClassFromString(actualProperty); - if (subModelClass == nil) { - NSString * first = [actualProperty substringToIndex:1]; - NSString * other = [actualProperty substringFromIndex:1]; - subModelClass = NSClassFromString([NSString stringWithFormat:@"%@%@",[first uppercaseString],other]); - } + WHC_ModelPropertyInfo * propertyInfo = [class getPropertyInfo:actualProperty]; + if (propertyInfo == nil) { + if (replacePropertyClassMap) { + propertyInfo = [WHC_ModelPropertyInfo new]; + [propertyInfo setClass:replacePropertyClassMap[actualProperty] valueClass:[obj class]]; + }else { + if ([class respondsToSelector:@selector(whc_ModelReplacePropertyClassMapper)]) { + [class setModelPropertyClassMapper:[class whc_ModelReplacePropertyClassMapper]]; } - if (subModelClass) { - ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [self handleDataModelEngine:subObject class:subModelClass]); - }else { - ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + propertyInfo = [self classExistProperty:actualProperty withObject:modelObject valueClass:[obj class]]; + } + if (propertyInfo) { + [class setModelInfo:propertyInfo property:actualProperty]; + }else { + return; + } + SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[actualProperty substringToIndex:1].uppercaseString, [actualProperty substringFromIndex:1]]); + if (![modelObject respondsToSelector:setter]) { + actualProperty = [self existproperty:actualProperty withObject:modelObject]; + if (actualProperty == nil) { + return; } - - }else{ - ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @[]); + setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",[actualProperty substringToIndex:1].uppercaseString, [actualProperty substringFromIndex:1]]); } - break; - case _Dictionary: - if(![subObject isKindOfClass:[NSNull class]]){ - Class subModelClass = NULL; - if (replaceContainerElementClassMap) { - subModelClass = replaceContainerElementClassMap[actualProperty]; - }else if ([class respondsToSelector:@selector(whc_ModelReplaceContainerElementClassMapper)]) { - replaceContainerElementClassMap = [class whc_ModelReplaceContainerElementClassMapper]; + propertyInfo->setter = setter; + } + switch (propertyInfo->type) { + case _Array: + if(![subObject isKindOfClass:[NSNull class]]){ + Class subModelClass = NULL; if (replaceContainerElementClassMap) { subModelClass = replaceContainerElementClassMap[actualProperty]; + }else if ([class respondsToSelector:@selector(whc_ModelReplaceContainerElementClassMapper)]) { + replaceContainerElementClassMap = [class whc_ModelReplaceContainerElementClassMapper]; + subModelClass = replaceContainerElementClassMap[actualProperty]; [class setContainerElementClassMapper:replaceContainerElementClassMap]; } + if (subModelClass == NULL) { + subModelClass = NSClassFromString(actualProperty); + if (subModelClass == nil) { + NSString * first = [actualProperty substringToIndex:1]; + NSString * other = [actualProperty substringFromIndex:1]; + subModelClass = NSClassFromString([NSString stringWithFormat:@"%@%@",[first uppercaseString],other]); + } + } + if (subModelClass) { + ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [self handleDataModelEngine:subObject class:subModelClass]); + }else { + ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + + }else{ + ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @[]); } - if (subModelClass == NULL) { - subModelClass = NSClassFromString(actualProperty); - if (subModelClass == nil) { - NSString * first = [actualProperty substringToIndex:1]; - NSString * other = [actualProperty substringFromIndex:1]; - subModelClass = NSClassFromString([NSString stringWithFormat:@"%@%@",[first uppercaseString],other]); + break; + case _Dictionary: + if(![subObject isKindOfClass:[NSNull class]]){ + Class subModelClass = NULL; + if (replaceContainerElementClassMap) { + subModelClass = replaceContainerElementClassMap[actualProperty]; + }else if ([class respondsToSelector:@selector(whc_ModelReplaceContainerElementClassMapper)]) { + replaceContainerElementClassMap = [class whc_ModelReplaceContainerElementClassMapper]; + if (replaceContainerElementClassMap) { + subModelClass = replaceContainerElementClassMap[actualProperty]; + [class setContainerElementClassMapper:replaceContainerElementClassMap]; + } + } + if (subModelClass == NULL) { + subModelClass = NSClassFromString(actualProperty); + if (subModelClass == nil) { + NSString * first = [actualProperty substringToIndex:1]; + NSString * other = [actualProperty substringFromIndex:1]; + subModelClass = NSClassFromString([NSString stringWithFormat:@"%@%@",[first uppercaseString],other]); + } } + if (subModelClass) { + NSMutableDictionary * subObjectDictionary = [NSMutableDictionary dictionary]; + [subObject enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { + [subObjectDictionary setObject:[self handleDataModelEngine:obj class:subModelClass] forKey:key]; + }]; + ((void (*)(id, SEL, NSDictionary *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObjectDictionary); + }else { + ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + + }else{ + ((void (*)(id, SEL, NSDictionary *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @{}); } - if (subModelClass) { - NSMutableDictionary * subObjectDictionary = [NSMutableDictionary dictionary]; - [subObject enumerateKeysAndObjectsUsingBlock:^(NSString * key, id _Nonnull obj, BOOL * _Nonnull stop) { - [subObjectDictionary setObject:[self handleDataModelEngine:obj class:subModelClass] forKey:key]; - }]; - ((void (*)(id, SEL, NSDictionary *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObjectDictionary); - }else { - ((void (*)(id, SEL, NSArray *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + break; + case _String: + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSString *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + }else{ + ((void (*)(id, SEL, NSString *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @""); } - - }else{ - ((void (*)(id, SEL, NSDictionary *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @{}); - } - break; - case _String: - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSString *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); - }else{ - ((void (*)(id, SEL, NSString *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @""); - } - break; - case _Number: - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSNumber *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); - }else{ - ((void (*)(id, SEL, NSNumber *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @(0)); - } - break; - case _Integer: - ((void (*)(id, SEL, NSInteger))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject integerValue]); - break; - case _UInteger: - ((void (*)(id, SEL, NSUInteger))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject unsignedIntegerValue]); - break; - case _Boolean: - ((void (*)(id, SEL, BOOL))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject boolValue]); - break; - case _Float: - ((void (*)(id, SEL, float))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject floatValue]); - break; - case _Double: - ((void (*)(id, SEL, double))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject doubleValue]); - break; - case _Char: - ((void (*)(id, SEL, char))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject charValue]); - break; - case _Model: - ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [self handleDataModelEngine:subObject class:propertyInfo->class]); - break; - case _Date: - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSDate *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); - } - break; - case _Value: - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSValue *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); - } - break; - case _Data: { - if(![subObject isKindOfClass:[NSNull class]]){ - ((void (*)(id, SEL, NSData *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + break; + case _Number: + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSNumber *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + }else{ + ((void (*)(id, SEL, NSNumber *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, @(0)); + } + break; + case _Integer: + ((void (*)(id, SEL, NSInteger))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject integerValue]); + break; + case _UInteger: + ((void (*)(id, SEL, NSUInteger))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject unsignedIntegerValue]); + break; + case _Boolean: + ((void (*)(id, SEL, BOOL))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject boolValue]); + break; + case _Float: + ((void (*)(id, SEL, float))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject floatValue]); + break; + case _Double: + ((void (*)(id, SEL, double))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject doubleValue]); + break; + case _Char: + ((void (*)(id, SEL, char))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [subObject charValue]); + break; + case _Model: + ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, [self handleDataModelEngine:subObject class:propertyInfo->class]); + break; + case _Date: + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSDate *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + break; + case _Value: + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSValue *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + break; + case _Data: { + if(![subObject isKindOfClass:[NSNull class]]){ + ((void (*)(id, SEL, NSData *))(void *) objc_msgSend)((id)modelObject, propertyInfo->setter, subObject); + } + break; } - break; + default: + + break; } - default: - - break; - } - }]; + }]; + } return modelObject; }else if ([object isKindOfClass:[NSArray class]]){ NSMutableArray * modelObjectArr = [NSMutableArray new];