「iOS」——YYModel学习

iOS学习

前言

YYModel是YYKit的高效组件之一,在实际场景中的非常实用,在项目中使用MVC架构时,可以简化数据处理。在性能上相比JSONMode更加高效。在此对使用做简单学习。


优势

原作者给出如下YYModel的优势:

  • 高性能:转换效率接近手写代码。
  • 自动类型转换:对象类型能自动转换。
  • 类型安全:在转换过程中所有的类型都会被验证,以确保类型安全。
  • 非侵入性:不需要让模型类继承自基类。
  • 轻量级:整个库只包含5个文件。
  • 文档和测试覆盖:100%文档覆盖,99.6代码覆盖。

使用方法

简单的Model与JSON互转

这里需要注意:

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

JSON/Dictionary Model
NSString NSNumber,NSURL,SEL,Class
NSNumber NSString
NSString/NSNumber 基础类型 (BOOL,int,float,NSUInteger,UInt64,...) NaN 和 Inf 会被忽略
NSString NSDate 以下列格式解析: yyy-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 格式化为 ISO8601: "YYYY-MM-dd'T'HH:mm:ssZ"
NSValue struct (CGRect,CGSize,...)
NSNull nil,0
"no","false",... @(NO),0
"yes","true",... @(YES),1

多样化的数据类型交换

YYModel支持自定义的属性名进行映射,即数据的key和属性名可以是不相同。那么怎么才知道你自定义的属性名对应的是数据的哪个key呢?那就需要对自定义属性的映射进行映射声明。

objectivec 复制代码
+ (NSDictionary *)modelCustomPropertyMapper {
   // 将personId映射到key为id的数据字段
    return @{@"personId":@"id"};
}

可以看到model和JSON获取的字典内容并不完全相同,这时候需要我们重写modelCustomPropertyMapper这个方法,使用一个字典将Model属性名对映射到 JSON 的 Key。这就是映射声明。

objectivec 复制代码
+ (NSDictionary *)modelCustomPropertyMapper {
   // 映射可以设定多个映射字段
   return @{@"realComments":@[@"long_comments",@"comments",@"short_comments"]};
}
objectivec 复制代码
// ViewController.m
Model *model = [Model modelWithDictionary:dic];
NSLog(@"realComments: %d",model.realComments);

你可以把一个或一组 json key (key path) 映射到一个或多个属性。如果一个属性没有映射关系,那默认会使用相同属性名作为映射。

在 json->model 的过程中:如果一个属性对应了多个 json key,那么转换过程会按顺序查找,并使用第一个不为空的值。

在 model->json 的过程中:如果一个属性对应了多个 json key (key path),那么转换过程仅会处理第一个 json key (key path);如果多个属性对应了同一个 json key,则转换过过程会使用其中任意一个不为空的值。


容器类数据交换

需要注意:要遵从< YYModel>协议,才会快捷提醒以下方法:

objectivec 复制代码
+ (nullable NSDictionary<NSString *, id> *)modelContainerPropertyGenericClass;
+ (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper;
+ (nullable NSArray<NSString *> *)modelPropertyWhitelist;
+ (nullable NSArray<NSString *> *)modelPropertyBlacklist;

如果Model是用一个容器类进行包装的话,我们就需要重写modelContainerPropertyGenericClass这个方法返回对应容器之中的Model类型

objectivec 复制代码
JSON:
{
  "date": "20241020",
  "stories": [
    {
      "image_hue": "0xaa7246",
      "title": "小事 ·「谢谢,这歌儿真好听,谢谢。」",
      "url": "https://daily.zhihu.com/story/9776246",
      "hint": "VOL.1594",
      "ga_prefix": "102007",
      "images": [
        "https://pica.zhimg.com/v2-36a74af2cbeb2950e23f4a21ae7c9afc.jpg?source=8673f162"
      ],
      "type": 0,
      "id": 9776246
    },
    {
      "image_hue": "0x3d342b",
      "title": "很多人都认为大学知识跟高中没有关系,那为什么还要上高中呢?为什么不能初中毕业直接上大学?",
      "url": "https://daily.zhihu.com/story/9776259",
      "hint": "荆公门下东坡首徒 · 10 分钟阅读",
      "ga_prefix": "102007",
      "images": [
        "https://picx.zhimg.com/v2-f1f397a7fa6a1062bee7edd106c49496.jpg?source=8673f162"
      ],
      "type": 0,
      "id": 9776259
    },
    {
      "image_hue": "0x3d342b",
      "title": "武松血溅鸳鸯楼时,张都监的手下为什么不来帮忙?",
      "url": "https://daily.zhihu.com/story/9776265",
      "hint": "娃娃鱼 · 6 分钟阅读",
      "ga_prefix": "102007",
      "images": [
        "https://picx.zhimg.com/v2-f1f397a7fa6a1062bee7edd106c49496.jpg?source=8673f162"
      ],
      "type": 0,
      "id": 9776265
    },
    {
      "image_hue": "0x3d342b",
      "title": "这世界上最毒的物质是什么?",
      "url": "https://daily.zhihu.com/story/9776272",
      "hint": "mekdull · 47 分钟阅读",
      "ga_prefix": "102007",
      "images": [
        "https://picx.zhimg.com/v2-f1f397a7fa6a1062bee7edd106c49496.jpg?source=8673f162"
      ],
      "type": 0,
      "id": 9776272
    }
  ],
  "top_stories": [
    {
      "image_hue": "0x42535e",
      "hint": "作者 / 赵学浩",
      "url": "https://daily.zhihu.com/story/9776126",
      "image": "https://picx.zhimg.com/v2-00604b295890258d35108f32921dfdf2.jpg?source=8673f162",
      "title": "《封神演义》为什么没有列入四大名著?",
      "ga_prefix": "101607",
      "type": 0,
      "id": 9776126
    },
    {
      "image_hue": "0xaa7246",
      "hint": "作者 / 田可乐",
      "url": "https://daily.zhihu.com/story/9776246",
      "image": "https://picx.zhimg.com/v2-520eb91c117bf9da4f62071961629b85.jpg?source=8673f162",
      "title": "小事 ·「谢谢,这歌儿真好听,谢谢。」",
      "ga_prefix": "102007",
      "type": 0,
      "id": 9776246
    },
    {
      "image_hue": "0x8e6238",
      "hint": "作者 / 赵泠",
      "url": "https://daily.zhihu.com/story/9776243",
      "image": "https://picx.zhimg.com/v2-e10faf6e06d42ddaae06fc8dc6e648b8.jpg?source=8673f162",
      "title": "人类以外的动物有没有把自己的食物驯化得好吃的行为?",
      "ga_prefix": "101907",
      "type": 0,
      "id": 9776243
    },
    {
      "image_hue": "0x1a1b37",
      "hint": "作者 / 朱锦平",
      "url": "https://daily.zhihu.com/story/9776238",
      "image": "https://pic1.zhimg.com/v2-5ea4434e6ba5a4e1810059ae1c6c052e.jpg?source=8673f162",
      "title": "黑洞周围的「事件视界」是什么?",
      "ga_prefix": "101807",
      "type": 0,
      "id": 9776238
    },
    {
      "image_hue": "0xb39e74",
      "hint": "作者 / 南行兮",
      "url": "https://daily.zhihu.com/story/9776232",
      "image": "https://picx.zhimg.com/v2-aaa227e7ccc5781303cc1d8e885b9768.jpg?source=8673f162",
      "title": "我为什么总觉得辛弃疾用典的词写的很一般,而不用典的写的很好?",
      "ga_prefix": "101707",
      "type": 0,
      "id": 9776232
    }
  ]
}


@class Stories, Top_stories;

@interface Model
@property NSString *date;
@property NSArray *stories; 
@property NSArray *top_stories; 
@end

@implementation Model
// 返回容器类中的所需要存放的数据类型 (以 Class 或 Class Name 的形式)。
+ (NSDictionary *)modelContainerPropertyGenericClass {
    return @{@"stories" : [stories class],
             @"top_stories" : top_stories.class,
}
@end

打印结果:

objectivec 复制代码
{
    date = 20241021;
    stories =     (
                {
            "ga_prefix" = 102107;
            hint = "\U8c46\U5b50 \U00b7 2 \U5206\U949f\U9605\U8bfb";
            id = 9775499;
            "image_hue" = 0x5d6341;
            images =             (
                "https://pic1.zhimg.com/v2-241803af186704cf830cb0a3ad9268d2.jpg?source=8673f162"
            );
            title = "\U5728\U4e2d\U56fd\U53e4\U4ee3\Uff0c\U7834\U4ea7\U7684\U7537\U4eba\U7684\U4f8d\U59be\U5982\U4f55\U81ea\U5904\Uff1f";
            type = 0;
            url = "https://daily.zhihu.com/story/9775499";
        },
                {
            "ga_prefix" = 102107;
            hint = "\U674e\U7965JasonLee \U00b7 3 \U5206\U949f\U9605\U8bfb";
            id = 9776310;
            "image_hue" = 0x261e1b;
            images =             (
                "https://picx.zhimg.com/v2-aa2257309051a31b36501c840bf8cfaa.jpg?source=8673f162"
            );
            title = "\U4e4b\U524d\U542c\U8bf4\U589e\U808c\U8981\U505a\U5230\U529b\U7aed\Uff0c\U4e3a\U4ec0\U4e48\U73b0\U5728\U53c8\U63d0\U5021\U300c\U4e0d\U529b\U7aed\U300d\U4e86\Uff1f";
            type = 0;
            url = "https://daily.zhihu.com/story/9776310";
        },
                {
            "ga_prefix" = 102107;
            hint = "\U859b\U52a8\U8c14\U7684\U55b5 \U00b7 3 \U5206\U949f\U9605\U8bfb";
            id = 9776311;
            "image_hue" = 0x191924;
            images =             (
                "https://pic1.zhimg.com/v2-3673082d8ee90b155a4ecd2b556954a4.jpg?source=8673f162"
            );
            title = "\U8bba\U6587\U5e38\U7528\U8bcd\U6c47 i.e.\Uff0ce.g.\Uff0cetc.\Uff0cviz.\Uff0cet al. \U7684\U524d\U4e16\U4eca\U751f";
            type = 0;
            url = "https://daily.zhihu.com/story/9776311";
        },
                {
            "ga_prefix" = 102106;
            hint = "VOL.3454";
            id = 9776346;
            "image_hue" = 0xb3b3b3;
            images =             (
                "https://pic1.zhimg.com/v2-b8a38efaf99a864356cef394c26becc0.jpg?source=8673f162"
            );
            title = "\U778e\U626f \U00b7 \U5982\U4f55\U6b63\U786e\U5730\U5410\U69fd";
            type = 0;
            url = "https://daily.zhihu.com/story/9776346";
        }
    );
    "top_stories" =     (
                {
            "ga_prefix" = 101607;
            hint = "\U4f5c\U8005 / \U8d75\U5b66\U6d69";
            id = 9776126;
            image = "https://picx.zhimg.com/v2-00604b295890258d35108f32921dfdf2.jpg?source=8673f162";
            "image_hue" = 0x42535e;
            title = "\U300a\U5c01\U795e\U6f14\U4e49\U300b\U4e3a\U4ec0\U4e48\U6ca1\U6709\U5217\U5165\U56db\U5927\U540d\U8457\Uff1f";
            type = 0;
            url = "https://daily.zhihu.com/story/9776126";
        },
                {
            "ga_prefix" = 102007;
            hint = "\U4f5c\U8005 / \U7530\U53ef\U4e50";
            id = 9776246;
            image = "https://picx.zhimg.com/v2-520eb91c117bf9da4f62071961629b85.jpg?source=8673f162";
            "image_hue" = 0xaa7246;
            title = "\U5c0f\U4e8b \U00b7\U300c\U8c22\U8c22\Uff0c\U8fd9\U6b4c\U513f\U771f\U597d\U542c\Uff0c\U8c22\U8c22\U3002\U300d";
            type = 0;
            url = "https://daily.zhihu.com/story/9776246";
        },
                {
            "ga_prefix" = 101907;
            hint = "\U4f5c\U8005 / \U8d75\U6ce0";
            id = 9776243;
            image = "https://picx.zhimg.com/v2-e10faf6e06d42ddaae06fc8dc6e648b8.jpg?source=8673f162";
            "image_hue" = 0x8e6238;
            title = "\U4eba\U7c7b\U4ee5\U5916\U7684\U52a8\U7269\U6709\U6ca1\U6709\U628a\U81ea\U5df1\U7684\U98df\U7269\U9a6f\U5316\U5f97\U597d\U5403\U7684\U884c\U4e3a\Uff1f";
            type = 0;
            url = "https://daily.zhihu.com/story/9776243";
        },
                {
            "ga_prefix" = 101807;
            hint = "\U4f5c\U8005 / \U6731\U9526\U5e73";
            id = 9776238;
            image = "https://pic1.zhimg.com/v2-5ea4434e6ba5a4e1810059ae1c6c052e.jpg?source=8673f162";
            "image_hue" = 0x1a1b37;
            title = "\U9ed1\U6d1e\U5468\U56f4\U7684\U300c\U4e8b\U4ef6\U89c6\U754c\U300d\U662f\U4ec0\U4e48\Uff1f";
            type = 0;
            url = "https://daily.zhihu.com/story/9776238";
        },
                {
            "ga_prefix" = 101707;
            hint = "\U4f5c\U8005 / \U5357\U884c\U516e";
            id = 9776232;
            image = "https://picx.zhimg.com/v2-aaa227e7ccc5781303cc1d8e885b9768.jpg?source=8673f162";
            "image_hue" = 0xb39e74;
            title = "\U6211\U4e3a\U4ec0\U4e48\U603b\U89c9\U5f97\U8f9b\U5f03\U75be\U7528\U5178\U7684\U8bcd\U5199\U7684\U5f88\U4e00\U822c\Uff0c\U800c\U4e0d\U7528\U5178\U7684\U5199\U7684\U5f88\U597d\Uff1f";
            type = 0;
            url = "https://daily.zhihu.com/story/9776232";
        }
    );
}

model中包含其他model

仅需让一个model属性包含另一个model即可。

objectivec 复制代码
// JSON
{
    "memory ":{
        "name":"lfc",
        "birthday":"2023-07-26"
    },
    "name":"yl",
    "age":17
}
 
// Model: 什么都不用做,转换会自动完成
@interface Memory : NSObject
@property NSString *name;
@property NSDate *birthday;
@end
@implementation Memory 
@end
 
@interface People : NSObject
@property NSString *name;
@property NSUInteger age;
@property Author *author; //People 包含 Memory  属性
@end
@implementation People
@end

白名单与黑名单

注意:黑白名单不同时使用

objectivec 复制代码
+ (NSArray<NSString *> *)modelPropertyBlacklist {
    return @[@"Memory"];
}//这个方法不会处理JSON数据中的这个数据
+ (NSArray<NSString *> *)modelPropertyWhitelist {
    return @[@"Memory"];
}//这个方法会让程序只处理JSON中的这个数据

总结

对YYModel的简单学习,后续还会对源码进行学习。

相关推荐
朝九晚五ฺ20 分钟前
【Linux探索学习】第九弹——Linux工具篇(四):项目自动化构建工具—make/Makefile
linux·运维·学习·ubuntu·自动化
Willliam_william1 小时前
SystemC学习(3)— APB_SRAM的建模与测试
学习·算法
smallcatlei6 小时前
ios 快捷指令扩展(Intents Extension)简单使用 swift语言
ios·swift
Y.O.U..8 小时前
STL学习-容器适配器
开发语言·c++·学习·stl·1024程序员节
T_Y994310 小时前
selenium学习日记
学习·selenium·测试工具
糊涂君-Q11 小时前
Python小白学习教程从入门到入坑------第十九课 异常模块与包【下】(语法基础)
开发语言·python·学习·程序人生·改行学it
爱编程的小新☆11 小时前
Java篇图书管理系统
java·开发语言·学习
致奋斗的我们12 小时前
RHCE的学习(7)
linux·服务器·网络·学习·redhat·rhce·rhcsa
孤客网络科技工作室14 小时前
深入学习 Scrapy 框架:从入门到精通的全面指南
学习·scrapy