【iOS】YYModel的初步学习

发布于:2024-10-13 ⋅ 阅读:(100) ⋅ 点赞:(0)

YYModel的初步学习

前言

随着时代的发展,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_modelWithJSONyy_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中的对象,方便我们对于数据进行操作处理。