解读MJExtension

介绍

关于MJExtension的介绍、使用官方已经介绍的很清楚了,请前往Github MJExtension.

MJExtension

这个框架可以快速的进行字典转模型,在实际开发中非常方便和稳定。那么这个框架是如果实现的呢?

  1. 这个框架利用了Runtime获取类的成员属性。
  2. 这个框架将所有的成员属性都封装成MJProperty对象。也就是一个成员属性对应着一个MJProperty的对象。
  3. 利用Runtime,对当前类进行一层一层的遍历,当模型类存在继承关系时,也是要进行处理的。
  4. 该框架不仅提供了字典转模型,也提供了模型转字典中功能。
  5. 解决了模型嵌套,以及复杂的模型数据问题。
    .....

MJProperty的成员属性

image.png

对于这个类的理解,应该是对propertyKeyDictobjectClassInArrayDict的理解和运用,关于这个下面有详细的介绍,现在先介绍关于type(成员属性的类型)介绍

type(成员属性的类型)

在该框架中type也被包装成了一个MJPropertyType类型的对象。关于MJPropertyType的成员属性请看下图。

image.png

MJPropertyType.m文件中我们会看到以下的一行代码

NSArray *numberTypes = @[MJPropertyTypeInt,MJPropertyTypeShort, MJPropertyTypeBOOL1, MJPropertyTypeBOOL2, MJPropertyTypeFloat, MJPropertyTypeDouble, MJPropertyTypeLong, MJPropertyTypeLongLong, MJPropertyTypeChar];
/**
*  成员变量类型(属性类型)
*/
NSString *const MJPropertyTypeInt = @"i";
NSString *const MJPropertyTypeShort = @"s";
NSString *const MJPropertyTypeFloat = @"f";
NSString *const MJPropertyTypeDouble = @"d";
NSString *const MJPropertyTypeLong = @"l";
NSString *const MJPropertyTypeLongLong = @"q";
NSString *const MJPropertyTypeChar = @"c";
NSString *const MJPropertyTypeBOOL1 = @"c";
NSString *const MJPropertyTypeBOOL2 = @"b";
NSString *const MJPropertyTypePointer = @"*";

NSString *const MJPropertyTypeIvar = @"^{objc_ivar=}";
NSString *const MJPropertyTypeMethod = @"^{objc_method=}";
NSString *const MJPropertyTypeBlock = @"@?";
NSString *const MJPropertyTypeClass = @"#";
NSString *const MJPropertyTypeSEL = @":";
NSString *const MJPropertyTypeId = @"@";

上述代码定义的是成员属性的类型编码,我们可以通过Runtime提供的const char * property_getAttributes(objc_property_t property)api来可以获取成员属性的描述信息,其中就包含了类型编码。
有关成员属性的描述信息和类型编码可以查看描述信息类型编码

成员属性的描述性信息表


image.png

声明的属性类型编码表


image.png

类型编码表

image.png

以上表格只是参考,建议去官网查询描述信息类型编码

举个例子

@interface MLStudent : NSObject
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) int age;
@property (assign, nonatomic) double weight;
@property (assign, nonatomic) double height;
@property (assign, nonatomic) struct objc_method *Method;
@property (assign, nonatomic) struct objc_ivar *Ivar;
@property (assign, nonatomic) void(^block)(void);
@property (strong, nonatomic) MLCar* myCar;

@end
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        unsigned int count;
        objc_property_t * property_ts =class_copyPropertyList([MLStudent class], &count);
        for (int i = 0; i < count; i ++) {
            objc_property_t  property_t  = property_ts[i];
   
          const char *  propertyAttributes_c =  property_getAttributes(property_t);
            NSString *propertyAttributes =  [[NSString alloc] initWithUTF8String:propertyAttributes_c];
            NSLog(@"Attributes:  %@",propertyAttributes);
            
           
            NSUInteger dotLoc = [propertyAttributes rangeOfString:@","].location;
            NSString *code = nil;
            NSUInteger loc = 1;
            if (dotLoc == NSNotFound) { // 没有,
                code = [propertyAttributes substringFromIndex:loc];
            } else {
                code = [propertyAttributes substringWithRange:NSMakeRange(loc, dotLoc - loc)];
            }
            NSLog(@"code: %@",code);
          
        }
        
    }
    return 0;
}

输出


image.png
image.png

通过上图的例子,我们可以获取每个属性的真实类型,在MJExtension中有一段代码就是获取成员属性的真实类型,然后包装成MJPropertyType类型的对象

image.png

目的就是获取 T后面的真实类型

T@"NSString",C,N,V_name

  • @"NSString":代表NSString类型,
  • C :代表采用copy策略
  • N :代表nonatomic非原子性
  • V_name : 代表name成员属性的名字

Ti,N,V_age

  • i:代表int类型
  • N:代表nonatomic非原子性
  • V_age:代表age成员属性的名字
    关于下面的类型里面的代码,代码里面介绍以及很详细了。

MJProperty成员属性的赋值流程

image.png

上面有提到关于propertyKeysDictobjectClassInArrayDict成员属性的理解,这里我采用图解的方式,关于详细的代码,还请查看官网的详细代码。
propertyKeysDict

image.png

objectClassInArrayDict
image.png

字典转模型

image.png

在字典转模型中,可以初略分为两大阶段

第一是准备阶段

  1. 将成员属性包装成MJProperty对象。
  2. 对象成员属性type类型的解析和包装MJPropertyType.
  3. 将key 以及多级key的拆分和包装MJPropertyKey.
  4. 以及对propertyKeysDictobjectClassInArrayDict的赋值。
    需要注意的是一个类中有多少个成员属性就会由多少个MJProperty对象,一个MJProperty对象可以拥有多个MJPropertyKey类型的对象(因为key 可能是多级映射)

第二阶段是使用阶段

  1. 通过回调的方式将MJProperty对象返回给外界的核心处理方法。
  2. 核心方法采用了通过对类型的判断采取递归的方式进行字典转模型。
  3. ...

MJEXtension中字典转模型 核心代码解读

- (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context

image.png

  1. 字典转模型,传入的必须是字典。
  2. 第一行代码是对象keyValues的处理,如果传入的是json字符串或者其他数据,首先需要转换为字典。
  3. 第二行代码是对传入类型的判断必须是字典
  4. 获取当前类的具体类型,通过类来获取那些属性是允许字典转模型,那些熟悉是不允许字典转模型。


    image.png

解读红色框住的部分

  1. 通过上述的介绍我们知道propertyKeysDict Value是一个二级数组 key是具体的类
  2. 通过类型和成员属性对象我们就可以通过双层for得到被包装的MJPropertyKey对象
    3.通过MJPropertyKey对象属性的name和传入的字典value,就可得到内层name对应的值,此时在将值赋值给value。(字典可以嵌套字典,通用模型也可以嵌套模型。这样就会出现多级key。在改框架中,对多级key进行了拆分,但是保留了他们的name,通过那么就可以在最外层的字段中查找对应的值了)
  3. 最后对value值的过滤,以及判空处理。
image.png
  1. 获取该成员属性的类型。
  2. 判断是否是一个类作为成员属性。
  3. 模型数据的具体类型。
image.png
  1. 标记为1的部分判断MJProperty *property是否是Foundation 类型 并且propertyClass确实存在一个类作为成员属性,那么就进行递归,再次调用高方法。
  2. 标记为2的部分是处理模型数组作为成员属性的。
image.png

最后一步是通过KVC进行赋值。

另外MJExtension提供了模型转字典,后续....

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容