봉인 MJExtension, 모형 회전 모형

8859 단어
MJExtension 은 모두 가 낯 설 지 않 을 것 이다. 그러나 MJExtensionjsonmodel 사이 에 서로 전환 하 는 구조 이다. http 협의 에서 이런 구 조 는 매우 편리 하 다. 그러면 어떻게 모델 을 모델 로 전환 시 킬 수 있 을 까?이 문 제 는 이상 할 수도 있 습 니 다. 이미 모델 입 니 다. 왜 바 꿔 야 합 니까? Protobuff 프로 토 콜 을 사용 한 사람들 이 모두 비슷 한 일 을 했 을 것 이 라 고 믿 습 니 다. PB 프로 토 콜 중의 모델 을 자신의 프로젝트 중의 모델 로 바 꿔 야 합 니 다. 이렇게 모델 이 많 으 면 뇌 장애 코드 를 많이 써 서 모델 에서 모델 로 바 꿔 야 합 니 다.
사실 사용 MJExtension 자체 가 모델 에서 모델 을 바 꿀 수 있다. 그것 은 바로 모델 을 사전 으로 바 꾼 다음 에 사전 을 모델 로 바 꾸 는 것 이다. 그러나 이렇게 되면 효율 에 문제 가 생 긴 다.
다음은 효율 적 인 전환 방법, 직접 모델 전환 방법 \ #
이것 은 MJ 사전 회전 모델 의 핵심 알고리즘 입 니 다 \ # \ #
- (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context

이것 은 MJ 모델 사전 전환 의 핵심 알고리즘 입 니 다 \ # \ #
- (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys

이 두 가지 기능 은 비슷 하기 때문에 우 리 는 이러한 방법 을 정의 하여 모델 전환 모델 을 한다.
+ (instancetype)pb_object:(id)srcModel;

여 기 는 클래스 방법 입 니 다. 핵심 알고리즘 은 - (instancetype)pb_object:(id)srcModel ignoredKeys:(NSArray *)ignoredKeys 입 니 다.
+ (instancetype)pb_object:(id)srcModel {
    return [self pb_object:srcModel ignoredKeys:nil];
}

+ (instancetype)pb_object:(id)srcModel ignoredKeys:(NSArray *)ignoredKeys {
    return [[[self alloc] init] pb_object:srcModel ignoredKeys:ignoredKeys];
}

- (instancetype)pb_object:(id)srcModel ignoredKeys:(NSArray *)ignoredKeys

다음은 바로 보 겠 습 니 다 - (instancetype)pb_object:(id)srcModel ignoredKeys:(NSArray *)ignoredKeys
- (instancetype)pb_object:(id)srcModel ignoredKeys:(NSArray *)ignoredKeys {
    //          ,       
    MJExtensionAssertError(![MJFoundation isClassFromFoundation:[self class]], (NSMutableDictionary *)self, [self class], @"         ")
    
    //    model      
    Class srcClazz = [srcModel class];
    NSArray *allowedPropertyNames = [srcClazz mj_totalAllowedPropertyNames];
    NSArray *ignoredPropertyNames = [srcClazz mj_totalIgnoredPropertyNames];
    [srcClazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
        @try {
            // 0.       
            if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return;
            if ([ignoredPropertyNames containsObject:property.name]) return;
            //            if (keys.count && ![keys containsObject:property.name]) return;
            if ([ignoredKeys containsObject:property.name]) return;
            
            // 1.     
            id value = [property valueForObject:srcModel];
            if (!value) return;
            
            //     
            id newValue = [srcClazz mj_getNewValueFromObject:srcModel oldValue:value property:property];
            if (newValue != value) { //        
                [property setValue:newValue forObject:srcModel];
                return;
            }
            
            //      ,     
            if (!value || value == [NSNull null]) return;
            
            // 2.    
            Class dstClazz = [self class];
            
            MJProperty *dstProperty = [dstClazz pb_propertyForPropertyName:property.name];
            MJPropertyType *type = dstProperty.type;
            Class propertyClass = type.typeClass;
            Class objectClass = [dstProperty objectClassInArrayForClass:[self class]];
            
            //     ->     
            if (propertyClass == [NSMutableArray class] && [value isKindOfClass:[NSArray class]]) {
                value = [NSMutableArray arrayWithArray:value];
            } else if (propertyClass == [NSMutableDictionary class] && [value isKindOfClass:[NSDictionary class]]) {
                value = [NSMutableDictionary dictionaryWithDictionary:value];
            } else if (propertyClass == [NSMutableString class] && [value isKindOfClass:[NSString class]]) {
                value = [NSMutableString stringWithString:value];
            } else if (propertyClass == [NSMutableData class] && [value isKindOfClass:[NSData class]]) {
                value = [NSMutableData dataWithData:value];
            }
            
            if (!type.isFromFoundation && propertyClass) { //     
                value = [propertyClass pb_object:value ignoredKeys:ignoredKeys];
            } else if (objectClass) {
                if (objectClass == [NSURL class] && [value isKindOfClass:[NSArray class]]) {
                    // string array -> url array
                    NSMutableArray *urlArray = [NSMutableArray array];
                    for (NSString *string in value) {
                        if (![string isKindOfClass:[NSString class]]) continue;
                        [urlArray addObject:string.mj_url];
                    }
                    value = urlArray;
                } else { //     -->    
                    value = [objectClass mj_objectArrayWithKeyValuesArray:value context:nil];
                }
            } else {
                if (propertyClass == [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 (propertyClass == [NSURL class]) {
                        // NSString -> NSURL
                        //      
                        value = [value mj_url];
                    } else if (type.isNumberType) {
                        NSString *oldValue = value;
                        
                        // NSString -> NSNumber
                        if (type.typeClass == [NSDecimalNumber class]) {
                            value = [NSDecimalNumber decimalNumberWithString:oldValue];
                        } else {
                            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;
                            }
                        }
                    }
                }
                
                // value property     
                if (propertyClass && ![value isKindOfClass:propertyClass]) {
                    value = nil;
                }
            }
            
            // 3.  
            [dstProperty setValue:value forObject:self];
        } @catch (NSException *exception) {
            MJExtensionBuildError([self class], exception.reason);
            MJExtensionLog(@"%@", exception);
        }
    }];
    
    return self;
}

코드 가 좀 길 지만 기본적으로 사전 회전 모델 과 는 다 릅 니 다.
 Class dstClazz = [self class]; 
 MJProperty *dstProperty = [dstClazz pb_propertyForPropertyName:property.name];
 MJPropertyType *type = dstProperty.type;
 Class propertyClass = type.typeClass;
 Class objectClass = [dstProperty objectClassInArrayForClass:[self class]];

원본 모델 의 속성 명 을 통 해 대상 모델 의 속성 을 가 져 옵 니 다.
+ (MJProperty *)pb_propertyForPropertyName:(NSString *)oldName {
    NSArray *cachedProperties = [self properties];
    
    for (MJProperty *property in cachedProperties) {
        NSString *propertyNewName = [self propertyKey:property.name];
        if ([propertyNewName isEqualToString:oldName]) {
            return property;
        }
    }
    return nil;
}

여기 cachedProperties 는 목표 모델 에 대응 하 는 모든 속성 이기 때문에 하나의 전환 을 하고 목표 모델 의 속성 명 에 대응 하 는 소스 모델 의 속성 명 을 찾 아야 한다. 즉 propertyNewName. 여기 도 근거 이다.
+ (NSDictionary *)replacedKeyFromPropertyName 

이 사전 은 진행 되 었 기 때문에 여 기 는 상대 적 으로 성능 을 소모 하 는 것 일 수 있 습 니 다. so, 이렇게 간단 합 니 다. 다른 곳 은 거의 변화 가 없습니다. MJ 의 프레임 워 크 를 이용 하여 자신의 모델 전환 방법 을 썼 습 니 다. 나중에 호출 할 때 가능 합 니 다.
BPDstModel *dstModel = [BPDstModel mj_object:srcModel];

이렇게 한 마디 로 해결 하 는 것 은 매우 간단 하지 않 습 니까?

좋은 웹페이지 즐겨찾기