「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的简单学习,后续还会对源码进行学习。

相关推荐
开心就好20251 天前
iOS App 安全加固流程记录,代码、资源与安装包保护
后端·ios
开心就好20251 天前
iOS App 性能测试工具怎么选?使用克魔助手(Keymob)结合 Instruments 完成
后端·ios
zhongjiahao2 天前
面试常问的 RunLoop,到底在Loop什么?
ios
wvy3 天前
iOS 26手势返回到根页面时TabBar的动效问题
ios
RickeyBoy3 天前
iOS 图片取色完全指南:从像素格式到工程实践
ios
aiopencode4 天前
使用 Ipa Guard 命令行版本将 IPA 混淆接入自动化流程
后端·ios
二流小码农4 天前
鸿蒙开发:路由组件升级,支持页面一键创建
android·ios·harmonyos
iceiceiceice5 天前
iOS PDF阅读器段评实现:如何从 PDFSelection 精准还原一个自然段
前端·人工智能·ios
ssshooter6 天前
Tauri 踩坑 appLink 修改后闪退
前端·ios·rust
二流小码农6 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos