• 一YYModel的使用场景

    • 简单的 Model 与 JSON 相互转换
    • Model 属性名和 JSON 中的 Key 不相同
    • Model 包含其他 Model
    • 容器类属性
    • 黑名单与白名单
    • 数据校验与自定义转换
    • CodingCopyinghashequaldescription
  • 二ESJsonFormat与YYModel的结合使用

开篇说明:
虽然网上有很多讲解YYModel使用方法的文章,包括YYModel作者也在github上对其做了使用说明。
但在我实际使用过程中,依然发现文档的不完善,比如对于复杂的模型(如多层嵌套)讲解的仍不透彻,同时本文也会介绍一神器配合YYModel使用,让你感受分分钟搞定模型创建的酸爽。
当然为了减少读者的学习成本,本会对YYModel作者的文档进行丰富和扩展。

可在github上下载Demo,以便更直观了解各种使用场景详细代码。
文章只要包含:

    1. 详解YYModel的多种使用场景
    1. 拓展插件,让你一分钟搞定所有的模型的创建和调用。

一、YYModel的使用场景

1.简单的 Model 与 JSON 相互转换

// JSON:
{"uid":123456,"name":"Harry","created":"1965-07-31T00:00:00+0000"
}// Model:
@interface User : NSObject
@property UInt64 uid;
@property NSString *name;
@property NSDate *created;
@end@implementation User
@end

-

// 将 JSON (NSData,NSString,NSDictionary) 转换为 Model:
User *user = [User yy_modelWithJSON:json];// 将 Model 转换为 JSON 对象:
NSDictionary *json = [user yy_modelToJSONObject];

当 JSON/Dictionary 中的对象类型与 Model 属性不一致时,YYModel 将会进行如下自动转换。自动转换不支持的值将会被忽略,以避免各种潜在的崩溃问题。

JSON/Dictionary Model
NSString NSNumber,NSURL,SEL,Class
NSNumber NSString
NSString/NSNumber C number (BOOL,int,float,NSUInteger,UInt64,…)
NaN and Inf will be ignored
NSString NSDate parsed with these formats:
yyyy-MM-dd
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd’T’HH:mm:ss
yyyy-MM-dd’T’HH:mm:ssZ
EEE MMM dd HH:mm:ss Z yyyy
NSDate NSString formatted with ISO8601:
“YYYY-MM-dd’T’HH:mm:ssZ”
NSValue struct (CGRect,CGSize,…)
NSNull nil,0
“no”,”false”,… @(NO),0
“yes”,”true”,… @(YES),1

2.Model 属性名和 JSON 中的 Key 不相同

// JSON:
{"n":"Harry Pottery","p": 256,"ext" : {"desc" : "A book written by J.K.Rowing."},"ID" : 100010
}// Model:
@interface Book : NSObject
@property NSString *name;
@property NSInteger page;
@property NSString *desc;
@property NSString *bookID;
@end
@implementation Book
//返回一个 Dict,将 Model 属性名对映射到 JSON 的 Key。
+ (NSDictionary *)modelCustomPropertyMapper {return @{@"name" : @"n",@"page" : @"p",@"desc" : @"ext.desc",@"bookID" : @[@"id",@"ID",@"book_id"]};
}
@end

你可以把一个或一组 json key (key path) 映射到一个或多个属性。如果一个属性没有映射关系,那默认会使用相同属性名作为映射。
在 json->model 的过程中:如果一个属性对应了多个 json key,那么转换过程会按顺序查找,并使用第一个不为空的值。
在 model->json 的过程中:如果一个属性对应了多个 json key (key path),那么转换过程仅会处理第一个 json key (key path);如果多个属性对应了同一个 json key,则转换过过程会使用其中任意一个不为空的值。

3.Model 包含其他 Model

// JSON
{"author":{"name":"J.K.Rowling","birthday":"1965-07-31T00:00:00+0000"},"name":"Harry Potter","pages":256
}// Model: 什么都不用做,转换会自动完成
@interface Author : NSObject
@property NSString *name;
@property NSDate *birthday;
@end
@implementation Author
@end@interface Book : NSObject
@property NSString *name;
@property NSUInteger pages;
@property Author *author; //Book 包含 Author 属性
@end
@implementation Book
@end

-

4.容器类属性

@class Shadow, Border, Attachment;@interface Attributes
@property NSString *name;
@property NSArray *shadows; //Array<Shadow>
@property NSSet *borders; //Set<Border>
@property NSMutableDictionary *attachments; //Dict<NSString,Attachment>
@end@implementation Attributes
// 返回容器类中的所需要存放的数据类型 (以 Class 或 Class Name 的形式)。
+ (NSDictionary *)modelContainerPropertyGenericClass {return @{@"shadows" : [Shadow class],@"borders" : Border.class,@"attachments" : @"Attachment" };
}
@end

在实际使用过过程中,[Shadow class]Border.class@"Attachment"没有明显的区别。
这里仅仅是创建作者有说明,实际使用时,需要对其遍历,取出容器中得字典,然后继续字典转模型。(YYModel的核心是通过runtime获取结构体中得Ivars的值,将此值定义为key,然后给key赋value值,所以我们需要自己遍历容器(NSArray,NSSet,NSDictionary),获取每一个值,然后KVC)。

-

  • 具体的代码实现如下:
NSDictionary *json =[self getJsonWithJsonName:@"ContainerModel"];
ContainerModel *containModel = [ContainerModel yy_modelWithDictionary:json];
NSDictionary *dataDict = [containModel valueForKey:@"data"];
//定义数组,接受key为list的数组
self.listArray = [dataDict valueForKey:@"list"]; //遍历数组
[self.listArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {NSDictionary *listDict = obj;//获取数组中得字典List *listModel = [List yy_modelWithDictionary:listDict];//获取count 和 idNSString *count = [listModel valueForKey:@"count"];NSString *id = [listModel valueForKey:@"id"];

-

5.黑名单与白名单

@interface User
@property NSString *name;
@property NSUInteger age;
@end@implementation Attributes
// 如果实现了该方法,则处理过程中会忽略该列表内的所有属性
+ (NSArray *)modelPropertyBlacklist {return @[@"test1", @"test2"];
}
// 如果实现了该方法,则处理过程中不会处理该列表外的属性。
+ (NSArray *)modelPropertyWhitelist {return @[@"name"];
}
@end

-

6.数据校验与自定义转换

实际这个分类的目的比较简单和明确。
就是对判断是否为时间戳,然后对时间戳进行处理,调用
_createdAt = [NSDate dateWithTimeIntervalSince1970:timestamp.floatValue];
获取时间。

// JSON:
{"name":"Harry","timestamp" : 1445534567     //时间戳
}// Model:
@interface User
@property NSString *name;
@property NSDate *createdAt;
@end@implementation User
// 当 JSON 转为 Model 完成后,该方法会被调用。
// 你可以在这里对数据进行校验,如果校验不通过,可以返回 NO,则该 Model 会被忽略。
// 你也可以在这里做一些自动转换不能完成的工作。
- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic {NSNumber *timestamp = dic[@"timestamp"];if (![timestamp isKindOfClass:[NSNumber class]]) return NO;_createdAt = [NSDate dateWithTimeIntervalSince1970:timestamp.floatValue];return YES;
}// 当 Model 转为 JSON 完成后,该方法会被调用。
// 你可以在这里对数据进行校验,如果校验不通过,可以返回 NO,则该 Model 会被忽略。
// 你也可以在这里做一些自动转换不能完成的工作。
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {if (!_createdAt) return NO;dic[@"timestamp"] = @(n.timeIntervalSince1970);return YES;
}
@end
  • 需要注意的时,如果用插件,对时间戳类型或默认创建为NSUInteger类型,需要将其更改为NSDate类型。

-

7.Coding/Copying/hash/equal/description

以下方法都是YYModel的简单封装,实际使用过程和系统方法区别不大。对其感兴趣的可以点进方法内部查看。

@interface YYShadow :NSObject <NSCoding, NSCopying>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) CGSize size;
@end@implementation YYShadow
// 直接添加以下代码即可自动完成
- (void)encodeWithCoder:(NSCoder *)aCoder { [self yy_modelEncodeWithCoder:aCoder];
}
- (id)initWithCoder:(NSCoder *)aDecoder {self = [super init];return [self yy_modelInitWithCoder:aDecoder];
}
- (id)copyWithZone:(NSZone *)zone { return [self yy_modelCopy];
}
- (NSUInteger)hash { return [self yy_modelHash];
}
- (BOOL)isEqual:(id)object { return [self yy_modelIsEqual:object];
}
- (NSString *)description { return [self yy_modelDescription];
}
@end

-

二、ESJsonFormat与YYModel的结合使用

彩蛋
给大家介绍一款插件,配合ESJsonFormat

配图:

使用方法:
快捷键:shift + control + J
插件安装方法比较简单,在此不赘述,不知道可自行google。

好处

    1. 可以直接将json数据复制,ESJsonFormat会根据数据类型自动生成属性。(建议还是要自行检查,比如时间戳,系统会默认帮你生成为NSUInteger,而我们想要的为NSDate类型)
    1. 对于多模型嵌套,不必创建多个文件,ESJsonFormat会自动在一个文件下创建多重类型,极其便捷。

-
至此YYModel的使用已讲解完毕,关于YYModel的底层核心是运用runtime获取类结构体中Ivars,进行KVC操作,然后根据不同情况进行分别处理
此处只是传递给大家一个概念,不展开讲解,网上有很多源码分析文章,可自学google学习。
文末,做个综述。
建议大家有时间一定要多看底层,分析源码。不要只会用,知其然不知其所以然。
如有错误欢迎指出,文毕,程序员注定不能做一个孤独的勇士,也欢迎大家加微信号bin5211bin学习交流。

《一篇文章全吃透》—YYModel的使用技巧相关推荐

  1. 2008安装完了找不到_防臭地漏哪种好?防臭地漏怎么安装?一篇文章全了解

    家庭生活中用水的地方很多,为了保障空气质量,业主一定要选择防臭地漏.防臭地漏哪种好?防臭地漏怎么安装?装一网一篇文章就让大家通通了解! 防臭地漏哪种好? 1.非常芯 非常芯是北京中建圣大环境科技发展有 ...

  2. ununtu20.04系统中如何划词翻译_如何高效阅读PDF外文文献,这一篇文章全搞定

    对于很多初学者而言,阅读外文文献时非常痛苦的.句型复杂.生词多以及读者本身对外文文献的排斥感,都是造成阅读障碍的主要因素. 当然,如果你学会以下小编分享的一些技巧,可能并不觉得阅读那么难熬. 首先:建 ...

  3. c4d如何把文字贴在物体表面_一篇文章带你了解C4D布光技巧

    相信很多刚接触C4d的小朋友对光线分布非常困惑.毕竟,有很多种光源.当我们做光分布的时候,我们应该播放什么样的光?这是一个值得考虑的问题.所以今天跟大家分享一些我自己的配光技巧,希望能对新入门的同学有 ...

  4. git使用教程-一篇文章全搞定哦

    Git使用教程 Git是什么 文章转载自 代码飞:https://code.bywind.cn/2018/07/14/170/ Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项 ...

  5. 如何高效阅读PDF外文文献,这一篇文章全搞定!

    对于很多初学者而言,阅读外文文献时非常痛苦的.句型复杂.生词多以及读者本身对外文文献的排斥感,都是造成阅读障碍的主要因素. 当然,如果你学会以下小编分享的一些技巧,可能并不觉得阅读那么难熬. 首先:建 ...

  6. 一篇文章全搞懂!B2B

    作为一名刚入行不久的电商新人,时常被各种专业名词搞的晕头转向,公司开会或者行业交流时候没听懂也只能假装呵呵一笑(话说这种呵呵一笑是什么态度!摔).痛心疾首,小编决定总结近期所有我听过的没听过的互联网专 ...

  7. 共享单车技术含量,一篇文章全说透了!

    共享单车已经成为了中国新四大发明之一,被输往了世界上很多城市.在我看来,虽然共享单车的实现并不复杂,其实质是一个典型的"物联网+互联网"应用.应用的一边是车(物).另一边是用户(人 ...

  8. 一篇文章看懂MySQL的多表连接(包含左/右/全外连接)

    MySQL的多表查询 这是第二次学习多表查询,关于左右连接还是不是很熟悉,因此重新看一下.小目标:一篇文章看懂多表查询!! 这篇博客是跟着宋红康老师学习的,点击此处查看视频,关于数据库我放在了Gith ...

  9. 一篇文章了解保险的全方面——IT工程师该怎么保护自己

    这是一篇面向IT工程师的保险科普文.本文的目的,是为了从IT工程师的角度,用一篇文章--尽可能少的篇幅和逻辑性的排版--来帮助大家入门保险,在不上当受骗的基础上,为自己.以及自己的小家增添一份保障. ...

最新文章

  1. 怎么去除图像亮度对图像质量评价的影响_图像质量评估指标 SSIM / PSNR / MSE
  2. 安卓突击:Android 动画有哪几种?
  3. 使用java调用Web天气服务
  4. python字符串与文本处理技巧(4): 格式化输出、令牌解析、串上串
  5. HTML/CSS学习笔记02【表单标签】
  6. C语言有序数组转为平衡的二叉树(附完整源码)
  7. win7系统电脑自动重启解决方法
  8. hibernate 学习笔记1
  9. python散点图如何设置外边框_如何绘制散点图的外围边框?
  10. 从迁移到Java 7的小技巧
  11. 【转载保存】java 23种设计模式 深入理解
  12. 几个预防并发搞垮下游服务的方法
  13. 直播带货时画质总是太差,你的视频转码方案可能要换了
  14. linux下find用法 find -name *.so -exec ll {} \;
  15. toStringequals方法
  16. C语言基础项目:200 行代码实现贪吃蛇,思路+源码详解
  17. 关于redis (error) CLUSTERDOWN Hash slot not served
  18. WiFi路由器的速度到底怎么算的?
  19. C#获取当前桌面路径
  20. Alpha Fold 2

热门文章

  1. 关于java中的反射
  2. 有道云笔记迁移到为知笔记
  3. 苹果xr十大隐藏功能_苹果手机有哪些隐藏小功能?【建议收藏】
  4. 光电耦合器的工作原理以及应用
  5. 微信大转盘 【案例源码】提供
  6. 联想Y450 MAC系统SD读卡器驱动
  7. jQuery 基础 筛选和遍历 jQuery 对象
  8. nodejs的http请求是报错 socket hang up
  9. 使用Python对Dicom文件进行读取与写入的实现(pydicom 和 SimpleITK)
  10. Linux 查看查找文件