美文网首页selector
MJExtension源码剖析

MJExtension源码剖析

作者: tangbin583085 | 来源:发表于2017-10-21 20:28 被阅读0次

MJExtension源码剖析( 3.0.13

感觉学习东西最好还是先独立思考,亲自尝试写,然后再学习别人的源代码,这样收获会更多,体会更深,这是我的真实体验。
上一篇简书,说在没看MJExtension源码之前,我自己尝试书写了简易版MJExtension功能框架。而近日探索了MJExtension源码之后,感觉很兴奋,因为我自己写的源码思路基本上和MJExtension源码思路相同,很庆幸! - -
好了,废话少说,看下MJ大神的实现思路。

1,转换JSon对象

参数里面的keyValues对象(可能为字典,NSString,或者Data)预处理统统转化为JSon对象

    keyValues = [keyValues mj_JSONObject];

具体转化代码如下

- (id)mj_JSONObject
{
    if ([self isKindOfClass:[NSString class]]) {
        return [NSJSONSerialization JSONObjectWithData:[((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
    } else if ([self isKindOfClass:[NSData class]]) {
        return [NSJSONSerialization JSONObjectWithData:(NSData *)self options:kNilOptions error:nil];
    }
    
    return self.mj_keyValues;
}

2,获取Class的所有属性(关键,核心)

利用OC语言的运行时机制,获取Class的属性,包括基本类型和复合类型属性,从而为后续KVC赋值提供服务。
关键代码如下

            objc_property_t *properties = class_copyPropertyList(c, &outCount);

返回的数组里面包含了该类的所有属性,以及该属性所包含的参数(很关键,后面的模型属性需要该参数识别)。
其实之前我也看了OC运行时的获取属性的另外一个函数,就是:

class_copyIvarList(Class _Nullable cls, unsigned int * _Nullable outCount) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

但是以上函数获取不了属性所对应的属性参数,也就是说,你属性中有一个NSArray,但是利用以上函数根本无法得知模型类型。

3,设置属性类型

为每一个属性设置类型,因为第二步已经拿到了该类的所有属性,就可以设置每一个属性所对应的类型,包括嵌套的model 或者 数组里面装载model,为第四步的赋值做准备。

        // 去掉@"和",截取中间的类型名称
        _code = [code substringWithRange:NSMakeRange(2, code.length - 3)];
        _typeClass = NSClassFromString(_code);
        _fromFoundation = [MJFoundation isClassFromFoundation:_typeClass];
        _numberType = [_typeClass isSubclassOfClass:[NSNumber class]];

当然MJ大神中间为我们处理很多类型情况,不像我那样只是简单的封装类型。

4,利用KVC赋值

利用OC语言的KVC,为每一个基本类型(包括NSString)赋值
,需要注意的是模型属性是不能直接赋值的,需要利用递归先完成基本类型封装才能进行模型属性的赋值,和我的思路是一致的~
我们可以看到:

if (!type.isFromFoundation && propertyClass) { // 模型属性
                value = [propertyClass mj_objectWithKeyValues:value context:context];
            }

总结

1,当然MJExtension里面还有原理,内容需要学习,而不是像我所说得那么简单,同时也鼓励大家先亲自思考一边,写一遍,然后再去看。
2,解答了困扰我的2个小问题,①连MJ大神也没找到通过泛型获取数组模型属性,从而推断OC可能尚未支持该功能。②我一直不敢肯定判断模型属性字符串条件,后来看了MJ判断模型语句相似,简单粗暴高效 - -

else if (code.length > 3 && [code hasPrefix:@"@\""]) {
        // 去掉@"和",截取中间的类型名称
        .....
    }

而我写的

if ([attrString containsString:@"T@\""] && [attrString containsString:@"&"] ) {

意思大致相同~

相关文章

网友评论

    本文标题:MJExtension源码剖析

    本文链接:https://www.haomeiwen.com/subject/jebiyxtx.html