美文网首页
iOS20-Runtime学习笔记(三)- 字典转模型

iOS20-Runtime学习笔记(三)- 字典转模型

作者: echo海猫 | 来源:发表于2020-04-24 20:59 被阅读0次

Runtime字典转模型是iOS开发中常用的一个数据转化的方法,其核心是利用runtime消息转发机制,利用objc_msgSend函数进行方法调用从而达到目的
其好处就是:
第一高效
第二可以随意增加属性,不用再用在.m中去写东西
第三对于任何模型通用,具有通用性
具体代码实现、实现方法的思路及代码如下:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject
@property(nonatomic, copy) NSString *name;
@property(nonatomic, copy) NSString *age;
@property(nonatomic, copy) NSString *height;
@property(nonatomic, copy) NSString *phone;

//json转Model
-(instancetype)initWithDictToModel:(NSDictionary *)dict;
-(NSDictionary *)modelToDict;

@end

NS_ASSUME_NONNULL_END
#import "Person.h"
#import <objc/runtime.h>
#import <objc/message.h>

@implementation Person

//通过runtime实现快速的字典转模型的方法
-(instancetype)initWithDictToModel:(NSDictionary *)dict{
    self = [super init];
    if (self) {
        //将字典的所有key遍历出来进行setter方法赋值
        for (NSString *key in dict) {
            //第一步:根据keys去写它的setter方法
            NSString *keySetter = [NSString stringWithFormat:@"set%@:",key.capitalizedString];
            SEL sel = NSSelectorFromString(keySetter);
            //第二步:拿到key所对应的value 因为可能回事bool int long nsstring,所以用id接收
            id value = dict[key];
            //接着就是实现setter方法了
            if (sel) {
                //因为objc_msgSend 需要做一个函数指针的强转 void 是因为objc_msgSend 无返回值
                ((void(*)(id,SEL,id))objc_msgSend)(self, sel, value);
            }
        }
    }
    return self;
}

//通过getter方法去获取它的值 放到字典中
-(NSDictionary *)modelToDict{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    //
    unsigned int count = 0;
    // An opaque type that represents an Objective-C declared property.获取声明的属性列表
    //但是要注意,凡是使用到class_copy...都需要free()释放;
    objc_property_t *propertys = class_copyPropertyList(NSClassFromString(@"Person"),&count);
    if (count == 0) {
        return nil;
    }
    //遍历它的属性列表,按钮字典转模型的方法,写一个getter方法,获取值
    for (int i = 0; i< count; i++) {
        //第一步:获取属性值
        //property_getName 返回的是一个C string ,此时我们用遍历的方式,就要用指针接收,然后根据指针移动获取他的属性值
        const char *propertyName = property_getName(propertys[i]);
        NSString *name = [NSString stringWithUTF8String:propertyName];
        SEL sel = NSSelectorFromString(name);
        if (sel) {
            id value = ((id(*)(id,SEL))objc_msgSend)(self, sel);
            //这个地方加一个判空处理,可以直接用到项目中去
            if (value) {
                [dict setObject:value forKey:name];
            }else{
                [dict setObject:@"" forKey:name];
            }
        }
    }
    free(propertys);
    return dict;
}

在控制器ViewController的调用如下:

//model ---> dict
Person *per = [[Person alloc]initWithDictToModel:@{@"name":@"yg",@"age":@"123",@"height":@"180",@"phone":@"199999989898",}];
NSLog(@"==== persn.name = %@",per.name);
    
//dict ---> model
NSDictionary *item = [per modelToDict];
NSLog(@"========  %@  ========",item);

相关文章

网友评论

      本文标题:iOS20-Runtime学习笔记(三)- 字典转模型

      本文链接:https://www.haomeiwen.com/subject/wjqsihtx.html