刚入行时就见过项目里有mode转化为字典的代码,后来用过MJExtension的第三方库,非常好用,其实原理就是利用runtime遍历所有属性值,然后进行转化。但是自己从来没有动手写过~~~今天亲自写一写
1.先用runtime遍历所有属性值
代码如下:
- (NSDictionary *)dicFromObject:(NSObject *)object {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
unsigned int count;
objc_property_t *propertyList = class_copyPropertyList([object class], &count);
for (int i = 0; i < count; i++) {
objc_property_t property = propertyList[i];
const char *cName = property_getName(property);
NSString *name = [NSString stringWithUTF8String:cName];
NSObject *value = [object valueForKey:name];//valueForKey返回的数字和字符串都是对象
if (value == nil) {
//null
//[dic setObject:[NSNull null] forKey:name];//这行可以注释掉?????
} else {
//model
[dic setObject:[self dicFromObject:value] forKey:name];
}
}
return [dic copy];
}
这时我发现上面的代码只能转化
简单的model
, 而value的可能情况很多,可能是数组
,可能是字典
,一会又发现数组或字典里可能嵌套数组或字典或model
,我的妈妈,单纯一个递归方法根本无法实现所有的情况,还需要再添加方法。这么复杂吗?我记得别人写时很简单呀。于是我百度了一下,几乎所有代码都是上述类似代码,我也是醉了。。这根本无法适用在实际的项目
里。
2.代码改进如下:
//model转化为字典
- (NSDictionary *)dicFromObject:(NSObject *)object {
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
unsigned int count;
objc_property_t *propertyList = class_copyPropertyList([object class], &count);
for (int i = 0; i < count; i++) {
objc_property_t property = propertyList[i];
const char *cName = property_getName(property);
NSString *name = [NSString stringWithUTF8String:cName];
NSObject *value = [object valueForKey:name];//valueForKey返回的数字和字符串都是对象
if ([value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]]) {
//string , bool, int ,NSinteger
[dic setObject:value forKey:name];
} else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
//字典或字典
[dic setObject:[self arrayOrDicWithObject:(NSArray*)value] forKey:name];
} else if (value == nil) {
//null
//[dic setObject:[NSNull null] forKey:name];//这行可以注释掉?????
} else {
//model
[dic setObject:[self dicFromObject:value] forKey:name];
}
}
return [dic copy];
}
需要单独处理字典或数组
代码如下:
//将可能存在model数组转化为普通数组
- (id)arrayOrDicWithObject:(id)origin {
if ([origin isKindOfClass:[NSArray class]]) {
//数组
NSMutableArray *array = [NSMutableArray array];
for (NSObject *object in origin) {
if ([object isKindOfClass:[NSString class]] || [object isKindOfClass:[NSNumber class]]) {
//string , bool, int ,NSinteger
[array addObject:object];
} else if ([object isKindOfClass:[NSArray class]] || [object isKindOfClass:[NSDictionary class]]) {
//数组或字典
[array addObject:[self arrayOrDicWithObject:(NSArray *)object]];
} else {
//model
[array addObject:[self dicFromObject:object]];
}
}
return [array copy];
} else if ([origin isKindOfClass:[NSDictionary class]]) {
//字典
NSDictionary *originDic = (NSDictionary *)origin;
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
for (NSString *key in originDic.allKeys) {
id object = [originDic objectForKey:key];
if ([object isKindOfClass:[NSString class]] || [object isKindOfClass:[NSNumber class]]) {
//string , bool, int ,NSinteger
[dic setObject:object forKey:key];
} else if ([object isKindOfClass:[NSArray class]] || [object isKindOfClass:[NSDictionary class]]) {
//数组或字典
[dic setObject:[self arrayOrDicWithObject:object] forKey:key];
} else {
//model
[dic setObject:[self dicFromObject:object] forKey:key];
}
}
return [dic copy];
}
return [NSNull null];
}
代码编码完毕,我写了两个类Foo,Moo
做测试:
Foo.h如下:
@interface Foo : NSObject
@property(nonatomic, assign) int pwd;
@property(nonatomic, strong) NSString *userName;
@property(nonatomic, assign) BOOL isUrl;
@property(nonatomic, strong) Moo *moo;
@property(nonatomic, strong) NSArray *emailList;
@property(nonatomic, strong) NSArray *manyMoo;
@property(nonatomic, strong) NSDictionary *childrenList;
@property(nonatomic, strong) NSDictionary *MooDic;
@end
Moo.h如下:
@interface Moo : NSObject
@property(nonatomic, strong) NSString *name;
@property(nonatomic, strong) NSString *pwd;
@property(nonatomic, strong) NSString *profile;
@end
测试代码如下:
Foo *foo = [[Foo alloc] init];
foo.userName = @"gaoyuqiang";
foo.userName = nil;
foo.pwd = 1234;
foo.isUrl = YES;
foo.emailList = @[@"sfa@234.com", @"2@34.com"];
Moo *moo = [[Moo alloc] init];
moo.name = @"moo";
moo.pwd = @"234";
moo.profile = @"mooooo";
foo.moo = moo;
Moo *moo1 = [[Moo alloc] init];
moo1.name = @"moo1";
moo1.pwd = @"234";
moo1.profile = @"mooooo";
Moo *moo2 = [[Moo alloc] init];
moo2.name = @"moo2";
moo2.pwd = @"234";
moo2.profile = @"mooooo";
foo.manyMoo = @[moo1, moo2];
foo.childrenList = @{@"name":@"gao", @"pwd":@"32424"};
foo.MooDic = @{@"1" : @{@"s1" : moo1, @"s2" : moo2, @"s3" : @[@"1", @"2"]}, @"2" : moo2};
NSDictionary *result = [self dicFromObject:foo];
NSLog(@"result=%@", result);
Log如下,无论如何嵌套都可以完全转化
2017-07-26 16:57:10.030 Testff[61302:2256815] result={
MooDic = {
1 = {
s1 = {
name = moo1;
profile = mooooo;
pwd = 234;
};
s2 = {
name = moo2;
profile = mooooo;
pwd = 234;
};
s3 = (
1,
2
);
};
2 = {
name = moo2;
profile = mooooo;
pwd = 234;
};
};
childrenList = {
name = gao;
pwd = 32424;
};
emailList = (
"sfa@234.com",
"2@34.com"
);
isUrl = 1;
manyMoo = (
{
name = moo1;
profile = mooooo;
pwd = 234;
},
{
name = moo2;
profile = mooooo;
pwd = 234;
}
);
moo = {
name = moo;
profile = mooooo;
pwd = 234;
};
pwd = 1234;
}
有时间再写一个字典转model的代码,思路应该跟这个是类似的。