RestKit valueTransformer не вызывается

Я использую RestKit для связи с конечными точками JSON. Конечная точка возвращает метку времени UNIX в «количестве миллисекунд». Но преобразователь RestKit по умолчанию предполагает, что это «количество секунд», и я получаю неправильное значение в NSDate.

Итак, я осмотрелся и обнаружил, что мне нужно использовать собственный valueTransformer, чтобы сообщить RestKit, как преобразовать мою метку времени. Вот код, который у меня есть.

+ (RKBlockValueTransformer*) timeIntervalInMillisecondsSince1970TwoWayTransformer {

    return [RKBlockValueTransformer valueTransformerWithValidationBlock:^BOOL(__unsafe_unretained Class sourceClass, __unsafe_unretained Class destinationClass) {
        // This transformer handles `NSNumber` <-> `NSDate` transformations
        NSLog(@"checking new transformer");
        return (([sourceClass isSubclassOfClass:[NSNumber class]] && [destinationClass isSubclassOfClass:[NSDate class]]) ||
                ([sourceClass isSubclassOfClass:[NSDate class]] && [destinationClass isSubclassOfClass:[NSNumber class]]));
    } transformationBlock:^BOOL(id inputValue, __autoreleasing id *outputValue, __unsafe_unretained Class outputValueClass, NSError *__autoreleasing *error) {
        NSLog(@"transforming");
        RKValueTransformerTestInputValueIsKindOfClass(inputValue, (@[ [NSNumber class], [NSDate class] ]), error);
        RKValueTransformerTestOutputValueClassIsSubclassOfClass(outputValueClass, (@[ [NSNumber class], [NSDate class] ]), error);
        if ([outputValueClass isSubclassOfClass:[NSDate class]]) {
            if ([inputValue isKindOfClass:[NSNumber class]]) {
                *outputValue = [NSDate dateWithTimeIntervalSince1970:[inputValue doubleValue] / 1000];
            }
        } else if ([outputValueClass isSubclassOfClass:[NSNumber class]]) {
            *outputValue = @((NSInteger)[inputValue timeIntervalSince1970] * 1000);
        }
        return YES;
    }];
}

Затем я добавляю этот преобразователь в преобразователь RestKit по умолчанию.

RKValueTransformer* transformer = [self timeIntervalInMillisecondsSince1970TwoWayTransformer];
[[RKValueTransformer defaultValueTransformer] addValueTransformer:transformer];

Но моему трансформатору никогда не звонят. Заявление NSLog, которое я написал в нем, никогда не выполняется!


Итак, я попробовал это - написать преобразователь для attributeMapping следующим образом:

RKValueTransformer* transformer = [self timeIntervalInMillisecondsSince1970TwoWayTransformer];
RKAttributeMapping *tokenExpiryMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"access_token_expiration" toKeyPath:@"accessTokenExpirationDate"];
tokenExpiryMapping.valueTransformer = transformer;
[userMapping addPropertyMapping:tokenExpiryMapping];

Но код не компилируется, когда я это делаю. Пишет: «Свойство valueTransformer не найдено в объекте типа RKAttributeMapping *». Я этого не понимаю. Все примеры, которые я видел в Интернете, в том числе с документацией RestKit, говорят: тоже самое. Во всех примерах устанавливается свойство valueTransformer объекта AttributeMapping. Даже Справочник по классам RestKit говорит, что я могу его установить. Но тогда почему не компилируется?


person Rahul Jiresal    schedule 12.11.2014    source источник


Ответы (3)


Так мне удалось, наконец, выяснить, в чем проблема.

Мой подфайл был настроен на использование RestKit 0.20.3. А затем я добавил RKValueTransformers в качестве еще одного Pod. Однако RestKit 0.20.3 и более ранние версии поставляются со своей собственной версией файлов RKValueTransformer (.h и .m). И эти старые версии RestKit не поддерживают добавление ваших собственных трансформеров, потому что они не используют более новую библиотеку RKValueTransformers.

Когда я обновил свою версию RestKit до новейшей версии (на самом деле все, что выше 0.21.0, будет работать), все стало работать нормально. Мне не нужно было добавлять модуль RKValueTransformers, потому что он добавляется автоматически как зависимость от RestKit.

person Rahul Jiresal    schedule 12.11.2014

Посмотрите на использование insertValueTransformer:atIndex: вместо addValueTransformer:, чтобы вы могли добавить его в начало списка, а не в конец.

person Wain    schedule 12.11.2014
comment
Я хотел добавить преобразователь NSString в NSNumber для обработки 32-битного переполнения. Трансформатор не вызывался, пока я не сделал это изменение. - person KIDdAe; 18.01.2017

В Swift я смог успешно создать преобразователь значений. Его цель — просто добавить временную метку downloadedOn в мою модель, поэтому я вообще не использую inputValue:

let downloadedMapping = RKAttributeMapping(fromKeyPath: "@self", toKeyPath: "downloadedOn")
downloadedMapping.valueTransformer = RKBlockValueTransformer(validationBlock: nil){ _, outputValue, _, error -> Bool in
        outputValue.memory = NSDate()
        return true

}
myMapping.addPropertyMapping(downloadedMapping)

Самым большим предостережением для меня было то, как я должен записывать значение в указатель outputValue, пока не понял, что мне не нужно использовать параметр inout, а нужно обращаться к свойству memory параметра outputValue.

Примечание. Я использую общий keyPath @self для другой стороны моего сопоставления свойств, чтобы я мог использовать это сопоставление для различных классов, имеющих свойство downloadedOn.

person Besi    schedule 30.01.2016