MJExtension简述
MJExtension是一个非常容易使用并且功能强大的第三方框架,用于模型(model)与JSON之间进行相互转化!帮助开发者可高效方便地进行数据格式的转换,大大节省了开发者的开发时间。而且开发者也可以进行自定义转换模型字段或者忽略某些需转换的字段等,一旦你的项目用上将会爱不释手!
预热
- 宏
#define MJExtensionAssertError(condition, returnValue, clazz, msg) \
[clazz setMj_error:nil]; \
if ((condition) == NO) { \
MJExtensionBuildError(clazz, msg); \
return returnValue;\
}
#define MJExtensionBuildError(clazz, msg) \
NSError *error = [NSError errorWithDomain:msg code:250 userInfo:nil]; \
[clazz setMj_error:error];
分析:通过判断condition是否成立来设置类的NSError,通过创建NSObject分类使用runtime来绑定类对应的当前错误mj_error。
- 加锁
// 信号量
#define MJExtensionSemaphoreCreate \
static dispatch_semaphore_t signalSemaphore; \
static dispatch_once_t onceTokenSemaphore; \
dispatch_once(&onceTokenSemaphore, ^{ \
signalSemaphore = dispatch_semaphore_create(1); \
});
#define MJExtensionSemaphoreWait \
dispatch_semaphore_wait(signalSemaphore, DISPATCH_TIME_FOREVER);
#define MJExtensionSemaphoreSignal \
dispatch_semaphore_signal(signalSemaphore);
分析:使用dispatch_semaphore_create创建一个信号量使得程序执行的线程安全,当有线程在执行时则加锁,保证其它线程处于等待中;
原理分析
- 字典转模型
- (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
{
// 获得JSON对象
keyValues = [keyValues mj_JSONObject];
// keyValues不是字典则返回不处理
MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], self, [self class], @"keyValues参数不是一个字典");
Class clazz = [self class];
// 检测是否有重写mj_allowedPropertyNames方法自定义允许转换的字段
NSArray *allowedPropertyNames = [clazz mj_totalAllowedPropertyNames];
// 检测是否有重写mj_ignoredPropertyNames方法自定义忽略不进行转换的字段
NSArray *ignoredPropertyNames = [clazz mj_totalIgnoredPropertyNames];
//通过封装的方法回调一个通过运行时编写的方法,property为转换模型中对应各属性生成的对象。
[clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
@try {
// 当前模型property.name不在允许转换字段的数组allowedPropertyNames里面,不做处理
if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return;
// 当前模型property.name在忽略转换字段的数组ignoredPropertyNames里面,也不做处理
if ([ignoredPropertyNames containsObject:property.name]) return;
// 取出相应的属性值
id value;
// 获取模型属性对应的key数组
NSArray *propertyKeyses = [property propertyKeysForClass:clazz];
for (NSArray *propertyKeys in propertyKeyses) {
value = keyValues;
for (MJPropertyKey *propertyKey in propertyKeys) {
// 获取propertyKey中name对应的值value
value = [propertyKey valueInObject:value];
}
if (value) break;
}
// 是否有实现mj_newValueFromOldValue设置获取新值
id newValue = [clazz mj_getNewValueFromObject:self oldValue:value property:property];
if (newValue != value) { // 有新值直接设置
[property setValue:newValue forObject:self];
return;
}
// 如果没有值,就直接返回
if (!value || value == [NSNull null]) return;
// 2.复杂处理
MJPropertyType *type = property.type;