又一周了,新学习了点东西,整理一下。目前坚持每周发两篇文章,至少有一篇是有点东西的。
本周第一篇。
我们平常都使用第三方框架给我们提供好的Dictionary
转Model
,比如:YYModel
等,笔者长时间机械使用,却不太明白怎么实现的,花了点时间学习了一下,自己做了一个简单的实现。
1、Dictionary
转 Model
;
首先Dictionary
转 Model
,的思路:
- 获取Dictionary的所有
key
- 根据Dictionary的
key
获取Value
;- 给对象发消息
照常,有一个Book
类
//Book.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Book : NSObject
@end
NS_ASSUME_NONNULL_END
//Book.m
#import "Book.h"
@implementation Book
@end
字典转模型
- (instancetype)initWithDictionary:(NSDictionary *)dic{
self = [super init];
if (self) {
//获取字典的所有keys
NSArray *allKeys = dic.allKeys;
//遍历keys
for (NSString *key in allKeys) {
//根据key获取value
id value = dic[key];
//发消息
NSString *methodName = [NSString stringWithFormat:@"set%@:",key.capitalizedString];
//获取方法编号
SEL sel = NSSelectorFromString(methodName);
//发消息
if (sel) {
//返回类型 (函数名*)(param1,param2....)
//((void (*)(id,SEL,NSString *))objc_msgSend)(self, sel, value);
objc_msgSend(self, sel, value);
}
}
}
return self;
}
编译之后报错了,Too many arguments to function call, expected 0, have 3
。
查询objc_msgSend
。
头文件告诉我们 These functions must be cast to an appropriate function pointer type before being called.
。
意思是:调用之前我们需要转换为一个适当的函数指针类型。
菜鸡笔者只能使用翻译了~~ 囧。
那这里的函数指针怎么用呢?
- 格式如下:
函数返回值 (函数名 *) (param1 类型, param2 类型, param3 类型, ...)
所以上述void objc_msgSend(void /* id self, SEL op, ... */ )
的类型为((void (*)(id, SEL, NSString *))objc_msgSend)(self, sel, value);
这里虽然有很多问题,逻辑什么都不严谨,但是知道了原理,就可以慢慢装修了。
2、Model
转 Dictionary
;
Model
转 Dictionary
,的思路:
- 获取
Model
的属性名称的String
(也就是字典的key
);- Dictionary的
[dictionary setValue:value forKey:key];
代码如下,注释都有:
//模型转字典
- (NSDictionary *)dictionaryWithModel{
/*
Model转Dictionary的思路:
1、获取Model的属性名称的String(也就是字典的key);
2、Dictionary的 [dictionary setValue:value forKey:key];
*/
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
//声明一个 int 类型的 outCount
unsigned int outCount = 0;
// typedef struct property_t *objc_property_t;
// class_copyPropertyList 获取一个对象的所有属性, 返回值为 objc_property_t 的 List
objc_property_t *propertyList = class_copyPropertyList([self class], &outCount);
//如果有属性存在
if (outCount > 0) {
for (int i = 0; i < outCount; i++) {
/*
struct property_t {
const char *name;
const char *attributes;
};
*/
//获取数组中的每一个元素 objc_property_t
objc_property_t property_t = propertyList[i];
//获取字符串类型的名字
const char *propertyName = property_getName(property_t);
NSString *name = [NSString stringWithUTF8String:propertyName];
//方法编号
SEL sel = NSSelectorFromString(name);
//发消息取值
id value = ((id (*)(id,SEL)) objc_msgSend)(self,sel);
//赋值
[dictionary setValue:value forKey:name];
}
//释放指针返回值
free(propertyList);
return dictionary;
}
//释放指针
free(propertyList);
return nil;
}
网友评论