前言
YYModel是YYKit的高效組件之一,在實際場景中的非常實用,運用于項目中使用MVC或MVVM架構時,使用model做數據處理。
- 自動轉換模型數據
- 自動檢測數據安全性,避免carch
- 無需繼承其他類,使用方便
- 適用model各種數據加載運用場景
在使用之前先展示一些YYModel比較常用的方法,后面會具體介紹用法
// 字典轉模型
+ (nullable instancetype)modelWithDictionary:(NSDictionary *)dictionary;
// json轉模型
+ (nullable instancetype)modelWithJSON:(id)json;
// 模型轉NSObject
- (nullable id)modelToJSONObject;
// 模型轉NSData
- (nullable NSData *)modelToJSONData;
// 模型轉json字符串
- (nullable NSString *)modelToJSONString;
// 模型深拷貝
- (nullable id)modelCopy;
// 判斷模型是否相等
- (BOOL)modelIsEqual:(id)model;
// 屬性數據映射,用來定義多樣化數據時轉換聲明
+ (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper;
// 屬性自定義類映射,用來實現自定義類的轉換聲明
+ (nullable NSDictionary<NSString *, id> *)modelContainerPropertyGenericClass;
// 屬性黑名單,該名單屬性不轉換為model
+ (nullable NSArray<NSString *> *)modelPropertyBlacklist;
// 屬性白名單,只有該名單的屬性轉換為model
+ (nullable NSArray<NSString *> *)modelPropertyWhitelist;
// JSON 轉為 Model 完成后,該方法會被調用,返回false該model會被忽略
// 同時可以在該model中做一些,轉換不能實現的操作,如NSDate類型轉換
- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic;
// Model 轉為 JSON 完成后,該方法會被調用,返回false該model會被忽略
// 同時可以在該model中做一些,轉換不能實現的操作,如NSDate類型轉換
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic
運用場景
1、簡單的數據交換
YYModel最簡單的使用,在正常的數據調用,創建一個model類YYPersonModel,增加幾個屬性。
// YYPersonModel.h
@interface YYPersonModel : NSObject
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) int age;
@property (copy, nonatomic) NSString *sex;
@end
接著在viewController導入<NSObject+YYModel.h>頭文件,直接進行賦值就可以了,數據類型可可以是JSON/Dictionary,具體的可以看<NSObject+YYModel.h>給出的方法。
// ViewController.m
NSDictionary *dic = @{
@"name":@"張三",
@"age":@(12),
@"sex":@"男"
};
// 將數據轉模型
YYPersonModel *model = [YYPersonModel modelWithDictionary:dic];
// 將模型轉數據
NSDictionary *dics = [model modelToJSONObject];
使用起來是不是變得特別方便,會自動根據key一一映射到對應的屬性中對數據進行賦值,事實上使用只調用modelWithDictionary一個方法,剩下的YYModel會幫你處理里面的數據,自動進行安全性判斷和值類型轉換。
2、自定義屬性映射數據交換
YYModel支持自定義的屬性名進行映射,即數據的key和屬性名可以是不相同。那么怎么才知道你自定義的屬性名對應的是數據的哪個key呢?那就需要對自定義屬性的映射進行映射聲明。例如該例子中的personId:
// YYPersonModel.h
@interface YYPersonModel : NSObject
@property (strong, nonatomic) NSNumber *personId;
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) int age;
@property (copy, nonatomic) NSString *sex;
@end
在YYPersonModel.m 重寫yymodel的方法modelCustomPropertyMapper,返回設定的映射值,并且YYModel提供多個字段的映射。
// YYPersonModel.m
+ (NSDictionary *)modelCustomPropertyMapper {
// 將personId映射到key為id的數據字段
return @{@"personId":@"id"};
// 映射可以設定多個映射字段
// return @{@"personId":@[@"id",@"uid",@"ID"]};
}
最后依然通過像原來的數據那樣,直接通過字典的方式進行模型轉換,當key為id時,會自動給personId賦值,達到我們需要的效果。
// ViewController.m
NSDictionary *dic = @{
@"id":@"123",
@"name":@"張三",
@"age":@(12),
@"sex":@"男"
};
YYPersonModel *model = [YYPersonModel modelWithDictionary:dic];
NSLog(@"ID: %@",model.personId);
NSDictionary *dics = [model modelToJSONObject];
NSLog(@"ID: %@", dics[@"id"]);
3、多樣化的數據類型交換
YYModel支持多樣化的數據類型,甚至字典,數組等數據,如果不存在,則該model會自動設置為null,該例子提出使用NSArray和NSDictionary作為數據,效果依然一樣
// YYPersonModel.h
@interface YYPersonModel : NSObject
@property (strong, nonatomic) NSNumber *personId;
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) int age;
@property (copy, nonatomic) NSString *sex;
@property (strong, nonatomic) NSArray *languages;
@property (strong, nonatomic) NSDictionary *job;
@end
不得不說YYModel還是考慮很全面的,不僅支持各種類型數據,甚至考慮到獲取到數據的層次關系并沒有那么完美,那么這個時候該怎么做呢。例如該例子中的獲取到sex,是嵌套在下一層,同樣的我們也需要去聲明:
// YYPersonModel.m
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"personId":@"id",
@"sex":@"sexDic.sex" // 聲明sex字段在sexDic下的sex
};
}
在數據中依然可以找到NSArray和NSDictionary和sexDic下的sex字段并轉化為模型
// ViewController.m
NSDictionary *dic = @{
@"id":@"123",
@"name":@"張三",
@"age":@(12),
@"sexDic":@{@"sex":@"男"},
@"languages":@[
@"漢語",@"英語",@"法語"
],
@"job":@{
@"work":@"iOS開發",
@"eveDay":@"10小時",
@"site":@"軟件園"
}
};
YYPersonModel *model = [YYPersonModel modelWithDictionary:dic];
4、自定義類數據轉換
項目使用過程中,我們會涉及到多個model嵌套使用的情況,關于自定義類的聲明,YYModel提供給我們另外一個方法modelContainerPropertyGenericClass。例如我們在屬性中定義了YYEatModel作為類型。
// YYPersonModel.h
@interface YYEatModel : NSObject
@property (copy, nonatomic)NSString *food;
@property (copy, nonatomic)NSString *date;
@end
@interface YYPersonModel : NSObject
@property (strong, nonatomic) NSNumber *personId;
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) int age;
@property (copy, nonatomic) NSString *sex;
@property (strong, nonatomic) NSArray *languages;
@property (strong, nonatomic) NSDictionary *job;
@property (strong, nonatomic) NSArray <YYEatModel *> *eats;
@end
使用modelContainerPropertyGenericClass對賦值的key進行聲明后,可直接賦值。
// YYPersonModel.m
+ (NSDictionary *)modelCustomPropertyMapper {
return @{
@"personId":@"id",
@"sex":@"sexDic.sex" // 聲明sex字段在sexDic下的sex
};
}
// 聲明自定義類參數類型
+ (NSDictionary *)modelContainerPropertyGenericClass {
// value使用[YYEatModel class]或YYEatModel.class或@"YYEatModel"沒有區別
return @{@"eats" : [YYEatModel class]};
}
// ViewController.m
NSDictionary *dic = @{
@"id":@"123",
@"name":@"張三",
@"age":@(12),
@"sexDic":@{@"sex":@"男"},
@"languages":@[
@"漢語",@"英語",@"法語"
],
@"job":@{
@"work":@"iOS開發",
@"eveDay":@"10小時",
@"site":@"軟件園"
},
@"eats":@[
@{@"food":@"西瓜",@"date":@"8點"},
@{@"food":@"烤鴨",@"date":@"14點"},
@{@"food":@"西餐",@"date":@"20點"}
]
};
YYPersonModel *model = [YYPersonModel modelWithDictionary:dic];
for (YYEatModel *eat in model.eats) {
NSLog(@"%@",eat.food);
}
5、YYModel數據的其他處理
在轉化過程中,YYModel提供了過濾的功能,可以將想要轉換的屬性或者不需要轉換的屬性加入到黑白名單中,通常不同時使用。
// YYPersonModel.m
// 黑白名單不同時使用
// 如果實現了該方法,則處理過程中會忽略該列表內的所有屬性
+ (NSArray *)modelPropertyBlacklist {
return @[@"sex", @"languages"];
}
// 如果實現了該方法,則處理過程中不會處理該列表外的屬性。
+ (NSArray *)modelPropertyWhitelist {
return @[@"eats"];
}
有時候轉換后的model并不是我們最終想要的,這個情況轉換結束時YYModel提供了校驗的接口,可以在該接口中,校驗轉換的結果返回false則直接忽略該model,同時可以在該接口中處理轉換過程中,不能處理的數據。
// YYPersonModel.m
// 當 JSON 轉為 Model 完成后,該方法會被調用。
- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic {
// 可以在這里處理一些數據邏輯,如NSDate格式的轉換
return YES;
}
// 當 Model 轉為 JSON 完成后,該方法會被調用。
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
return YES;
}
最后在Model使用過程中,往往會遇到一個深拷貝的問題,為了不改變原model的數據,YYModel也提供了一個接口實現深拷貝。至于不懂深拷貝的同學可以先去網上了解一下
// ViewController.m
// 深拷貝model
YYPersonModel *model2 = [model modelCopy];
總結
到這里為止,關于YYModel的詳細使用方法已經寫完,基本上所有的使用場景都會在,如果有什么疑問可以給我留言。