iOS KVC (十)模型转换

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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,868评论 8 265
  • 为加大社会保险宣传力度,推进城镇企业职工养老保险制度健康稳步运行,26日,绥滨县社保局开展了以“社会保险,...
    丁小孩阅读 4,216评论 0 0
  • 曾经的我有段时间非常迷恋奇葩说。被里面的辩论深深吸引,我常常感叹,他们真的是为辩论而生,她们的妙语连珠,精彩纷呈,...
    深夜灵感阅读 1,371评论 0 0
  • 朋友圈充斥着每个朋友对2017的美好回忆。 而对我来说,这是极度不平凡的一年。 2017,1月7日回到汕头,决定要...
    Oh_930f阅读 1,111评论 0 0
  • 我爱无名的罪 大地的根深埋土壤 钻透人世间的悲欢离合 我也爱世俗的眼 天空的鱼是彻底的蓝 自由地遨翔是终生的命 我...
    伍月的晴空阅读 1,709评论 8 8