iOS学习笔记iOS 开发 iOS Developer

Mantle源码学习笔记

2016-07-23  本文已影响164人  升级打怪啊怪

介绍一下Mantle吧,Mantle是应用于iOS中dictionary转为model的一个第三方库,功能强大,容错覆盖好。以下是我跟着源码调用栈看下去的内容,只是懂了个大概,里面还是有挺多黑魔法的,KVC ,runtime运行时方法去获取propertylist什么的,还有transformer挺巧妙的。看看源码挺好哒

User *user =  [MTLJSONAdaptermodelOfClass:[Userclass]fromJSONDictionary:dicterror:nil];

一、 初始化MTLJSONAdapter:

MTLJSONAdapter *adapter = [[self alloc] initWithModelClass:modelClass];

1、_JSONKeyPathsByPropertyKey = modelClass JSONKeyPathsByPropertyKey];
这是Model遵守MTLJSONSerializing协议要实现的方法,指定对象的属性如何映射到不同的key path

2、NSSet *propertyKeys = [self.modelClass propertyKeys];
沿着superclass链向上遍历至MTLModel,获取model及父类中所有属性及其存储类型(除了存储类型为MTLPropertyStorageNone)

3、 for (NSString *mappedPropertyKey in _JSONKeyPathsByPropertyKey)
1)遍历JSONKeyPathsByPropertyKey变量,判断他们是否包含在propertyKeys集合中,
a)如果在propertyKeys集合中找不到JSONKeyPathsByPropertyKey中的属性,判断他不是该model的一个property.
b) 如果包含则获取对应属性keypath,这里keyPath有两种形式,字符串和数组
2)_valueTransformersByPropertyKey = [self.class valueTransformersForModelClass:modelClass];获取model中每个属性对应的值转换的字典。
具体实现过程:先去判断是否实现”属性名称”+”JSONTransformer”方法,如果实现进行动态调用并返回。如果未实现则判断是否实现JSONTransformerForKey这个方法,如果实现则进行调用并返回。如果未实现,则对属性结构进行判断,返回合适的值转换器。这里因为我们实现了URLJSONTransformer这个方法,所以代用完URLJSONTransformer就直接返回了。

二、 将JSON转换为model最主要的方法:

[adapter modelFromJSONDictionary:JSONDictionary error:error];

1、classForParsingJSONDictionary??
2、 遍历propertyKeys,for (NSString *propertyKey in [self.modelClass propertyKeys])
1)id JSONKeyPaths = self.JSONKeyPathsByPropertyKey[propertyKey];
获取property的的keypath.
2)如果keypath是数组类型,遍历该数组,比较keypath和JSONDictionary中的路径,检查keypath是否合法。并取回JSONDictionary中该keypath下的value.
id value = [JSONDictionary mtl_valueForJSONKeyPath:keyPath success:&success error:error];
对keypath进行拆分,比如user.name.firstName先分解成user,name,firstName,然后一层一层的获取user[name][firstName].用了个for循环,来给用户反馈,到底错误在哪里。
如果keypath是字符串类型,比较keypath和JSONDictionary中的路径,检查keypath是否合法。并取回JSONDictionary中该keypath下的value.
3) 判断相应属性是否存在值转换器,如果存在,则对值进行相应转换。
NSValueTransformer *transformer = self.valueTransformersByPropertyKey[propertyKey];
如果该property的value是NSNull.null, Map NSNull -> nil
a)如果 [transformer respondsToSelector:@selector(transformedValue:success:error:)]?? value = [errorHandlingTransformer transformedValue:value success:&success error:error];??
else value = [transformer transformedValue:value];

  1. 最后将所有的值存储在字典dictionaryValue中,并调用modelWithDictionary:error通过KVC的方式验证并设置值
    id model = [self.modelClass modelWithDictionary:dictionaryValue error:error];
    a)MTLModel中,(instancetype)initWithDictionary:(NSDictionary *)dictionary error:(NSError **)error,通过KVC的方式初始化model实例
    // 将value标记为__autoreleasing,这是因为在MTLValidateAndSetValue函数中,可以会返回一个新的对象存在在该变量中
    __autoreleasing id value = [dictionary objectForKey:key]; //先是遍历了字典,获取值并验证是否为NSNull.null类型
    if ([value isEqual:NSNull.null]) value = nil; //接着通过KVC的方式为model实例验证并设置值
    BOOL success = MTLValidateAndSetValue(self, key, value, YES, error);

写不出可以给别人看或者给自己看的东西,真是挺痛苦的。我是有用心去总结去写的,无奈结果总是不满意。why....

上一篇下一篇

猜你喜欢

热点阅读