核心代码
/**
核心代码:
*/
- (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error
{
// 获得JSON对象
keyValues = [keyValues JSONObject];
MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], self, error, @"keyValues参数不是一个字典");
@try {
Class aClass = [self class];
NSArray *allowedPropertyNames = [aClass totalAllowedPropertyNames];
NSArray *ignoredPropertyNames = [aClass totalIgnoredPropertyNames];
//通过封装的方法回调一个通过运行时编写的,用于返回属性列表的方法。
[aClass enumerateProperties:^(MJProperty *property, BOOL *stop) {
// 0.检测是否被忽略
if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return;
if ([ignoredPropertyNames containsObject:property.name]) return;
// 1.取出属性值
id value = keyValues ;
NSArray *propertyKeys = [property propertyKeysFromClass:aClass];
for (MJPropertyKey *propertyKey in propertyKeys) {
value = [propertyKey valueInObject:value];
}
// 值的过滤
id newValue = [aClass getNewValueFromObject:self oldValue:value property:property];
if (newValue) value = newValue;
// 如果没有值,就直接返回
if (!value || value == [NSNull null]) return;
// 2.如果是模型属性
MJPropertyType *type = property.type;
Class typeClass = type.typeClass;
Class objectClass = [property objectClassInArrayFromClass:[self class]];
if (!type.isFromFoundation && typeClass) {
value = [typeClass objectWithKeyValues:value context:context error:error];
} else if (objectClass) {
// string array -> url array
if (objectClass == [NSURL class] && [value isKindOfClass:[NSArray class]]) {
NSMutableArray *urlArray = [NSMutableArray array];
for (NSString *string in value) {
if (![string isKindOfClass:[NSString class]]) continue;
[urlArray addObject:string.url];
}
value = urlArray;
} else {
// 3.字典数组-->模型数组
value = [objectClass objectArrayWithKeyValuesArray:value context:context error:error];
}
} else if (typeClass == [NSString class]) {
if ([value isKindOfClass:[NSNumber class]]) {
// NSNumber -> NSString
value = [value description];
} else if ([value isKindOfClass:[NSURL class]]) {
// NSURL -> NSString
value = [value absoluteString];
}
} else if ([value isKindOfClass:[NSString class]]) {
if (typeClass == [NSURL class]) {
// NSString -> NSURL
// 字符串转码
value = [value url];
} else if (type.isNumberType) {
NSString *oldValue = value;
// NSString -> NSNumber
value = [_numberFormatter numberFromString:oldValue];
// 如果是BOOL
if (type.isBoolType) {
// 字符串转BOOL(字符串没有charValue方法)
// 系统会调用字符串的charValue转为BOOL类型
NSString *lower = [oldValue lowercaseString];
if ([lower isEqualToString:@"yes"] || [lower isEqualToString:@"true"]) {
value = @YES;
} else if ([lower isEqualToString:@"no"] || [lower isEqualToString:@"false"]) {
value = @NO;
}
}
}
}
// 4.赋值
[property setValue:value forObject:self];
}];
// 转换完毕
if ([self respondsToSelector:@selector(keyValuesDidFinishConvertingToObject)]) {
[self keyValuesDidFinishConvertingToObject];
}
} @catch (NSException *exception) {
MJExtensionBuildError(error, exception.reason);
NSLog(@"%@", exception);
}
return self;
}
获取对象的每一个属性,包括父类的属性,不包括NSObject,代码如下
+ (void)enumerateProperties:(MJPropertiesEnumeration)enumeration
{
// 获得成员变量
NSArray *cachedProperties = [self properties];
// 遍历成员变量
BOOL stop = NO;
for (MJProperty *property in cachedProperties) {
enumeration(property, &stop);
if (stop) break;
}
}
取出属性值,代码如下
// 1.取出属性值
id value = keyValues ;
NSArray *propertyKeys = [property propertyKeysFromClass:aClass];
for (MJPropertyKey *propertyKey in propertyKeys) {
value = [propertyKey valueInObject:value];
}
对象类型的值的处理,经过循环处理最终变成非对象,非数组的类型,代码如下
value = [typeClass objectWithKeyValues:value context:context error:error];
数组类型的值的处理,经过循环处理最终变成非对象,非数组的类型,代码如下
value = [objectClass objectArrayWithKeyValuesArray:value context:context error:error];
赋值,代码如下
[property setValue:value forObject:self];
MJExtension做了兼容处理,例如NSNumber,NSURL类型可以转换为NSString,代码如下
else if (typeClass == [NSString class]) {
if ([value isKindOfClass:[NSNumber class]]) {
// NSNumber -> NSString
value = [value description];
} else if ([value isKindOfClass:[NSURL class]]) {
// NSURL -> NSString
value = [value absoluteString];
}
}
网友评论