YYModel的初步学习
文章目录
- YYModel的初步学习
- 前言
- 与JSONModel对比
- YYModel的优势
- 如何使用YYModel
- 最简单的Model形式
- 容器类属性
- 白名单和黑名单
- Model的嵌套
- 小结
前言
随着时代的发展,iOS解析JSON数据的第三方库越来越多,原先的JSONModel的性能上的问题逐渐显现,现在我们可以采用更加高效的第三方库YYModel。
与JSONModel对比
时间消耗(在 iPhone 6 上处理 GithubUser 10000 次):
这里我们可以看出YYModel的性能其实超过了JSONModel,笔者在下文中仅仅介绍对于YYModel的使用,至于他与JSONModel的源码笔者会之后再进行学习。
YYModel的优势
- 高性能:转换性能接近手写代码。
- 自动类型转换:对象类型可以自动转换。
- 类型安全:将验证所有数据类型以确保在转换过程中类型安全。
- 非侵入式:无需使模型类继承其他基类。
- 轻量化:此库仅包含 5 个文件。
- 文档和单元测试:100% 的文档覆盖率,99.6% 的代码覆盖率。
如何使用YYModel
最简单的Model形式
// 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
// Convert json to model:
User *user = [User yy_modelWithJSON:json];
// Convert model to json:
NSDictionary *json = [user yy_modelToJSONObject];
我们使用YYModel的时候,只需要按照JSON数据中的名字,然后创建一个对象中设置属性名字和JSON数据中相同,然后我们需要在网络请求中调用yy_modelWithJSON
和yy_modelToJSONObject
这两个方法。一个是将JSON转化成model数据,另一个则是将model数据转化成NSObject
这两个类。
这里我们简单将这段代码放在网络请求中:
-(void)dataLoad {
NSString* urlString = @"https://devapi.qweather.com/v7/weather/3d?location=101010100&key=2211750bdc834763ba3c5f57ce98c307";
//NSURL* url = [NSURL URLWithString:urlString];
[[AFHTTPSessionManager manager] GET:urlString parameters:nil headers:nil progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
tryModel* model = [tryModel yy_modelWithJSON:responseObject];
NSDictionary* dirty = [model yy_modelToJSONObject];
NSLog(@"%@", dirty);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error");
}];
}
我们只需要简单结合网络请求和YYModel便可以实现对于JSON数据的一个解析,这里笔者采用了之前用过的和风天气的api
容器类属性
这里先给出我们这里的JSON数据:
{
"code": "200",
"updateTime": "2024-10-08T20:18+08:00",
"fxLink": "https://www.qweather.com/weather/beijing-101010100.html",
"daily": [
{
"fxDate": "2024-10-08",
"sunrise": "06:18",
"sunset": "17:47",
"moonrise": "11:40",
"moonset": "20:33",
"moonPhase": "蛾眉月",
"moonPhaseIcon": "801",
"tempMax": "23",
"tempMin": "10",
"iconDay": "100",
"textDay": "晴",
"iconNight": "151",
"textNight": "多云",
"wind360Day": "180",
"windDirDay": "南风",
"windScaleDay": "1-3",
"windSpeedDay": "3",
"wind360Night": "180",
"windDirNight": "南风",
"windScaleNight": "1-3",
"windSpeedNight": "3",
"humidity": "64",
"precip": "0.0",
"pressure": "1010",
"vis": "25",
"cloud": "25",
"uvIndex": "4"
},
{
"fxDate": "2024-10-09",
"sunrise": "06:19",
"sunset": "17:46",
"moonrise": "12:41",
"moonset": "21:28",
"moonPhase": "蛾眉月",
"moonPhaseIcon": "801",
"tempMax": "20",
"tempMin": "11",
"iconDay": "305",
"textDay": "小雨",
"iconNight": "151",
"textNight": "多云",
"wind360Day": "90",
"windDirDay": "东风",
"windScaleDay": "1-3",
"windSpeedDay": "3",
"wind360Night": "0",
"windDirNight": "北风",
"windScaleNight": "1-3",
"windSpeedNight": "16",
"humidity": "24",
"precip": "1.0",
"pressure": "1012",
"vis": "24",
"cloud": "55",
"uvIndex": "3"
},
{
"fxDate": "2024-10-10",
"sunrise": "06:20",
"sunset": "17:44",
"moonrise": "13:36",
"moonset": "22:32",
"moonPhase": "上弦月",
"moonPhaseIcon": "802",
"tempMax": "21",
"tempMin": "7",
"iconDay": "100",
"textDay": "晴",
"iconNight": "150",
"textNight": "晴",
"wind360Day": "0",
"windDirDay": "北风",
"windScaleDay": "1-3",
"windSpeedDay": "3",
"wind360Night": "225",
"windDirNight": "西南风",
"windScaleNight": "1-3",
"windSpeedNight": "3",
"humidity": "42",
"precip": "0.0",
"pressure": "1010",
"vis": "25",
"cloud": "25",
"uvIndex": "4"
}
],
"refer": {
"sources": [
"QWeather"
],
"license": [
"CC BY-SA 4.0"
]
}
}
这里我们可以看到这里的daily里面包含了一个数组,而那个数组里面有包含了另一个Model。所以说这里的JSON数据包含了一个容器类的属性,这里我们需要调用一下+ (NSDictionary *)modelContainerPropertyGenericClass
这个方法,这个方法是让我们的NSArray
或者NSSet
这些容器知道里面的存储的元素是什么对象:
- 这里注意下让这个类继承YYModel这个协议,否则会找不到这个方法
@interface Model : NSObject
@property (nonatomic, strong) NSString* fxDate;
@property (nonatomic, strong) NSString* sunrise;
@property (nonatomic, strong) NSString* sunset;
@property (nonatomic, strong) NSString* moonrise;
@property (nonatomic, strong) NSString* moonset;
@property (nonatomic, strong) NSString* moonPhase;
//@property (nonatomic, strong) NSString* moonPhaseIcon;
@property (nonatomic, strong) NSString* tempMax;
@property (nonatomic, strong) NSString* tempMin;
@property (nonatomic, strong) NSString* iconDay;
@property (nonatomic, strong) NSString* textDay;
@property (nonatomic, strong) NSString* iconNight;
@property (nonatomic, strong) NSString* textNight;
@property (nonatomic, strong) NSString* wind360Day;
@property (nonatomic, strong) NSString* windDirDay;
@property (nonatomic, strong) NSString* windScaleDay;
@property (nonatomic, strong) NSString* windSpeedDay;
@property (nonatomic, strong) NSString* wind360Night;
@property (nonatomic, strong) NSString* windDirNight;
@property (nonatomic, strong) NSString* windScaleNight;
@property (nonatomic, strong) NSString* windSpeedNight;
@property (nonatomic, strong) NSString* humidity;
@property (nonatomic, strong) NSString* precip;
@property (nonatomic, strong) NSString* pressure;
@property (nonatomic, strong) NSString* vis;
@property (nonatomic, strong) NSString* cloud;
@property (nonatomic, strong) NSString* uvIndex;
@end
@interface tryModel : NSObject<YYModel>
@property (nonatomic, strong) NSString* code;
@property (nonatomic, copy) NSArray* daily;
@end
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{@"daily":[Model class]};
}
这里我们可以看到这里的数组里面存储的也是一个Model,所以我们在这个方法里面给他一个字典让这个属性对应Model
的这个class,所以我们就可以让他进行一个Model的解析了。下面给出网络请求和YYModel数据结合
@implementation Model
-(void)dataLoad {
NSString* urlString = @"https://devapi.qweather.com/v7/weather/3d?location=101010100&key=2211750bdc834763ba3c5f57ce98c307";
//NSURL* url = [NSURL URLWithString:urlString];
[[AFHTTPSessionManager manager] GET:urlString parameters:nil headers:nil progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
tryModel* model = [tryModel yy_modelWithJSON:responseObject];
NSDictionary* dirty = [model yy_modelToJSONObject];
NSLog(@"%@", dirty);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error");
}];
}
@end
@implementation tryModel
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{@"daily":[Model class]};
}
@end
打印结果:
code = 200;
daily = (
{
cloud = 55;
fxDate = "2024-10-09";
humidity = 26;
iconDay = 305;
iconNight = 151;
moonPhase = "\U86fe\U7709\U6708";
moonrise = "12:41";
moonset = "21:28";
precip = "1.0";
pressure = 1013;
sunrise = "06:19";
sunset = "17:46";
tempMax = 21;
tempMin = 11;
textDay = "\U5c0f\U96e8";
textNight = "\U591a\U4e91";
uvIndex = 3;
vis = 24;
wind360Day = 270;
wind360Night = 0;
windDirDay = "\U897f\U98ce";
windDirNight = "\U5317\U98ce";
windScaleDay = "1-3";
windScaleNight = "1-3";
windSpeedDay = 3;
windSpeedNight = 16;
},
{
cloud = 25;
fxDate = "2024-10-10";
humidity = 40;
iconDay = 100;
iconNight = 150;
moonPhase = "\U4e0a\U5f26\U6708";
moonrise = "13:36";
moonset = "22:32";
precip = "0.0";
pressure = 1011;
sunrise = "06:20";
sunset = "17:44";
tempMax = 21;
tempMin = 8;
textDay = "\U6674";
textNight = "\U6674";
uvIndex = 4;
vis = 25;
wind360Day = 0;
wind360Night = 225;
windDirDay = "\U5317\U98ce";
windDirNight = "\U897f\U5357\U98ce";
windScaleDay = "1-3";
windScaleNight = "1-3";
windSpeedDay = 3;
windSpeedNight = 3;
},
{
cloud = 25;
fxDate = "2024-10-11";
humidity = 47;
iconDay = 100;
iconNight = 150;
moonPhase = "\U76c8\U51f8\U6708";
moonrise = "14:22";
moonset = "23:44";
precip = "0.0";
pressure = 1015;
sunrise = "06:21";
sunset = "17:42";
tempMax = 23;
tempMin = 11;
textDay = "\U6674";
textNight = "\U6674";
uvIndex = 4;
vis = 25;
wind360Day = 180;
wind360Night = 45;
windDirDay = "\U5357\U98ce";
windDirNight = "\U4e1c\U5317\U98ce";
windScaleDay = "1-3";
windScaleNight = "1-3";
windSpeedDay = 3;
windSpeedNight = 3;
}
);
}
Type: Notice | Timestamp: 2024-10-09 10:38:01.586475+08:00 | Process: YYModel | Library: YYModel | TID: 0x12795b1
这里就可以打印出JSON数据
白名单和黑名单
+ (NSArray<NSString *> *)modelPropertyBlacklist {
return @[@"updateTime"];
}//这个方法不会处理JSON数据中的这个数据
+ (NSArray<NSString *> *)modelPropertyWhitelist {
return @[@"daily"];
}//这个方法会让提仅仅处理JSON中的这个数据
如果实现这两个方法可以让我们获得我们所需要的数据
Model的嵌套
什么也不用做,我们只需要让一个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
小结
本篇文章简单介绍了如何将网络请求中得到的数据转化成我们OC中的对象,方便我们对于数据进行操作处理。