iOS KVC(一)基本了解
iOS KVC (二) 不可不知的赋值深层次原理
iOS KVC (三)不可不知的取值深层次原理
iOS KVC (四)keyPath的深度解析
iOS KVC (五)KVC几种典型的异常处理
iOS KVC (六) KVC容器类及深层次原理
iOS KVC(七) KVC正确性的验证
iOS KVC (八) KVC几种常见应用
iOS KVC (九) KVC模型转化(1) 模型打印 description, debugDescription
iOS KVC (十)模型转换(2)模型转换
本章主要讲单层次的模型转换 后期学习任务归结到 YYModel ,JsonModel,MJExtension的源码分析是会不发 此章也是模型转换的基础。
1传统设置方法
直接上代码
1.Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,strong)NSString *name;
@property (nonatomic,assign)int age;
+ (instancetype)personWithDict:(NSDictionary *)dict;
- (instancetype)initWithDict:(NSDictionary *)dict;
@end
2.Person.m
#import "Person.h"
#import <objc/runtime.h>
@implementation Person
- (NSString *)description{
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
//得到当前class的所有属性
uint count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (int i = 0; i<count; i++) {
objc_property_t property = properties[i];
NSString *name = @(property_getName(property));
id value = [self valueForKey:name]?:[NSNull null];//默认值不可为为nil的字符串
[dic setObject:value forKey:name];
}
free(properties);
return [NSString stringWithFormat:@"%@:%@",[self class],dic];
}
+ (instancetype)personWithDict:(NSDictionary *)dict {
return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];
if (self) {
// 方法 1,直接设置,基本数据类型需要转换
_name = dict[@"name"];
_age = [dict[@"age"] intValue];
}
return self;
}
3.实例调用
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSDictionary *dic = @{
@"name":@"小明",
@"age":@10,
@"address":@"河南"
};
Person *p = [Person personWithDict:dic];
NSLog(@"%@",p);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
4.打印数据
018-05-18 20:50:38.774764+0700 KVCDemo[4798:382355] Person:{
age = 10;
name = "\U5c0f\U660e";
}
5.总结:
无论字典中有没有包含模型的字段,都不会导致崩溃,包含赋值,不包含不赋值,多不退,少不补。
2KVC基础设置方法
1.Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy)NSString * _Nullable name;
@property (nonatomic,assign)int age;
@property (nonnull,copy)NSString *adress;
+ (instancetype _Nullable )personWithDict:(NSDictionary *_Nullable)dict;
- (instancetype _Nullable )initWithDict:(NSDictionary *_Nullable)dict;
@end
2.Person.m
#import "Person.h"
#import <objc/runtime.h>
@implementation Person
- (NSString *)description{
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
//得到当前class的所有属性
uint count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (int i = 0; i<count; i++) {
objc_property_t property = properties[i];
NSString *key = @(property_getName(property));
id value = [self valueForKey:key]?:[NSNull null];//此处不能为nil 因为字典中尽量不要出现nil 应该为[NSNull null]
[dic setObject:value forKey:key];
}
free(properties);
return [NSString stringWithFormat:@"%@:%@",[self class],dic];
}
+ (instancetype)personWithDict:(NSDictionary *)dict {
return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];
if (self) {
[self setValue:dict[@"name"] forKey:@"name"];
[self setValue:dict[@"age"] forKey:@"age"];
[self setValue:dict[@"adress"] forKey:@"adress"];
}
return self;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"不存在Key:%@",key);
}
- (void)setNilValueForKey:(NSString *)key{
NSLog(@"属性值不能为nil");
}
@end
3.调用
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSDictionary *dic = @{
@"name":[NSNull null],
@"adress":@"河南",
@"age":@10
};
Person *p = [Person personWithDict:dic];
NSLog(@"%@",p);
}
4.打印数据:
2018-05-18 22:38:44.749136+0700 KVCDemo[6297:464723] Person:{
adress = "\U6cb3\U5357";
age = 10;
name = "<null>";
}
5.总结:
1 - (void)setValue:(id)value forUndefinedKey:(NSString *)key
模型中不存在这个key会调用此方法。
2- (void)setNilValueForKey:(NSString *)key
当模型中的整形不存在时调用此方法。 并且如果整形不存在系统会将0赋予这个整型的字段。
3.这两个方法是必须执行的,因为如果不执行,如果存在不存在的key 或者模型的整形字段不存在,都会导致程序的崩溃。
3遍历字典
1.Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy)NSString * _Nullable name;
@property (nonatomic,assign)int age;
@property (nonnull,copy)NSString *adress;
+ (instancetype _Nullable )personWithDict:(NSDictionary *_Nullable)dict;
- (instancetype _Nullable )initWithDict:(NSDictionary *_Nullable)dict;
@end
2.Person.m
#import "Person.h"
#import <objc/runtime.h>
@implementation Person
- (NSString *)description{
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
//得到当前class的所有属性
uint count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (int i = 0; i<count; i++) {
objc_property_t property = properties[i];
NSString *key = @(property_getName(property));
id value = [self valueForKey:key]?:[NSNull null];//此处不能为nil 因为字典中尽量不要出现nil 应该为[NSNull null]
[dic setObject:value forKey:key];
}
free(properties);
return [NSString stringWithFormat:@"%@:%@",[self class],dic];
}
+ (instancetype)personWithDict:(NSDictionary *)dict {
return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];
if (self) {
for (NSString *key in dict) {
id value = dict[key];
[self setValue:value forKey:key];
}
}
return self;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"不存在Key:%@",key);
}
- (void)setNilValueForKey:(NSString *)key{
NSLog(@"属性值不能为nil");
}
- (BOOL)validatePersonName:(id *)value error:(out NSError * _Nullable __autoreleasing *)outError
{
NSString *name = *value;
if ([name isEqualToString:@"小明"]) {
return YES;
}
return NO;
}
3.调用
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSDictionary *dic = @{
@"name":[NSNull null],
@"adress":@"河南",
@"age":@10
};
Person *p = [Person personWithDict:dic];
NSLog(@"%@",p);
}
4.打印数据:
2018-05-19 16:17:55.638697+0700 KVCDemo[7364:534839] Person:{
adress = "\U6cb3\U5357";
age = 10;
name = "<null>";
}
5.总结:
写到此刻我已经无话可说了,只是一种方式。
4. setValuesForKeysWithDictionary
1.Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy)NSString * _Nullable name;
@property (nonatomic,assign)int age;
@property (nonnull,copy)NSString *adress;
+ (instancetype _Nullable )personWithDict:(NSDictionary *_Nullable)dict;
- (instancetype _Nullable )initWithDict:(NSDictionary *_Nullable)dict;
@end
2.Person.m
#import "Person.h"
#import <objc/runtime.h>
@implementation Person
- (NSString *)description{
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
//得到当前class的所有属性
uint count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (int i = 0; i<count; i++) {
objc_property_t property = properties[i];
NSString *key = @(property_getName(property));
id value = [self valueForKey:key]?:[NSNull null];//此处不能为nil 因为字典中尽量不要出现nil 应该为[NSNull null]
[dic setObject:value forKey:key];
}
free(properties);
return [NSString stringWithFormat:@"%@:%@",[self class],dic];
}
+ (instancetype)personWithDict:(NSDictionary *)dict {
return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];
if (self) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"不存在Key:%@",key);
}
- (void)setNilValueForKey:(NSString *)key{
NSLog(@"属性值不能为nil");
}
- (BOOL)validatePersonName:(id *)value error:(out NSError * _Nullable __autoreleasing *)outError
{
NSString *name = *value;
if ([name isEqualToString:@"小明"]) {
return YES;
}
return NO;
}
3.调用
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSDictionary *dic = @{
@"name":[NSNull null],
@"adress":@"河南",
@"age":@10
};
Person *p = [Person personWithDict:dic];
NSLog(@"%@",p);
}
4.打印数据:
2018-05-19 16:29:15.202777+0700 KVCDemo[7492:542825] Person:{
adress = "\U6cb3\U5357";
age = 10;
name = "<null>";
}
5.总结:
此方法等同于遍历字典,设置数据,等同于方法3
分享几篇关于模型多层转化的文章,希望对大家有所帮助。
iOS - 教你一步一步实现自己的字典转模型库
iOS开发·runtime+KVC实现多层字典模型转换(多层数据:模型嵌套模型,模型嵌套数组,数组嵌套模型)
到此为止关于KVC的基础知识就已经完结了,希望对你有所帮助。接下分享KVO。