剛入行時就見過項目里有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];
}
這時我發(fā)現上面的代碼只能轉化
簡單的model, 而value的可能情況很多,可能是數組,可能是字典,一會又發(fā)現數組或字典里可能嵌套數組或字典或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的代碼,思路應該跟這個是類似的。