前文介绍了 YYModel 怎么字典转模型,
概述
本文继续探讨,modelMeta
,存放模型的属性、和字典的键对应关系的描述文件
结构:
主要使用四个模型:
@interface YYClassPropertyInfo : NSObject
对应模型的属性
@interface YYClassInfo : NSObject
对应模型的类
包含属性字典,NSDictionary<NSString *, YYClassIvarInfo *>
@interface _YYModelPropertyMeta : NSObject
对应模型的属性,及其处理
包含一个成员变量 YYClassPropertyInfo *_info
,
把模型取得的属性 YYClassPropertyInfo
及其处理,封装在一起
@interface _YYModelMeta : NSObject
对应模型的类,及其处理
包含一个成员变量 YYClassInfo *_classInfo
,
把模型取得的类信息 YYClassInfo
及其处理,封装在一起
模型,为什么这么设计
下面,通过两个例子来介绍
例子一, + (NSDictionary *)modelCustomPropertyMapper
模型如下:
@interface Author : NSObject
@property NSString *name;
@property NSString *birthday;
@end
@implementation Author
@end
@interface Book : NSObject
@property NSString *name;
@property NSUInteger pages;
@property Author *reporter;
@end
@implementation Book
+ (NSDictionary *)modelCustomPropertyMapper {
return @{@"pages" : @"p",
@"reporter" : @[@"author",@"writer"]};
}
@end
代码实现
_YYModelMeta : NSObject
的实现中
先标记
- 对于
[ @"pages" : @"p" ]
,
通过下面的成员变量,维护一层映射关系
NSDictionary *_mapper;
- 对于
[ @"reporter" : @[@"author",@"writer"]
,
通过下面的成员变量,持有记录
NSArray *_multiKeysPropertyMetas;
具体实现
- (instancetype)initWithClass:(Class)cls {
// ...
NSMutableDictionary *mapper = [NSMutableDictionary new];
// ...
if ([cls respondsToSelector:@selector(modelCustomPropertyMapper)]) {
NSDictionary *customMapper = [(id <YYModel>)cls modelCustomPropertyMapper];
[customMapper enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSString *mappedToKey, BOOL *stop) {
_YYModelPropertyMeta *propertyMeta = allPropertyMetas[propertyName];
if (!propertyMeta) return;
// allPropertyMetas 删除 @"pages" 对应的
// allPropertyMetas 删除 @"reporter" 对应的
[allPropertyMetas removeObjectForKey:propertyName];
if ([mappedToKey isKindOfClass:[NSString class]]) {
// 处理这个 ,
// [ @"pages" : @"p" ]
if (mappedToKey.length == 0) return;
propertyMeta->_mappedToKey = mappedToKey;
NSArray *keyPath = [mappedToKey componentsSeparatedByString:@"."];
for (NSString *onePath in keyPath) {
if (onePath.length == 0) {