美文网首页
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