RestKitTransformer value not being called

I am using RestKit to talk to my JSON endpoints. The endpoint returns the UNIX timestamp in "milliseconds". But RestKit default transformer assumes it is "number of seconds" and I am getting wrong value in NSDate.

So I looked around and found that I need to use a custom valueTransformer to tell RestKit how to transform my timestamp. Here is the code I have.

+ (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;
    }];
}

      

Then I add this transformer to the RestKit default transformer.

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

      

But my transformer is never called. The statement NSLog

I wrote in it never runs!


So I tried this - writing a transformer on the attribute Machine:

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

      

But the code doesn't compile when I do this. He says: "The valueTransformer property was not found on an object of type 'RKAttributeMapping *'. I don't understand that. All the examples I've seen on the Internet, including those from the RestKit documentation , say the same thing. All examples set an valueTransformer

object property AttributeMapping

. Even the link RestKit class says I can install it, but then why doesn't it compile?

+3


source to share


3 answers


So, I finally managed to figure out what the problem is.

My podfile was configured to use RestKit 0.20.3. And then I added RKValueTransformers

as another Pod. However, RestKit 0.20.3 and earlier have their own version of RKValueTransformer files (.h and .m). And those old RestKit versions don't support adding their own transformers because they don't use the new library RKValueTransformers

.



When I updated my RestKit version to the newest version (in fact anything above 0.21.0 would have worked) everything started working fine. I didn't need to add the pod RKValueTransformers because it is automatically added as a RestKit dependency.

+2


source


Look at usage insertValueTransformer:atIndex:

instead addValueTransformer:

so you can add it at the beginning of the list and not at the end.



+1


source


In swift, I can successfully create a value transformer. Its purpose is to just add a timestamp downloadedOn

to my model, so I don't use at all 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)

      

The biggest caveat for me was how I should write the value to the pointer outputValue

until I figure out that I don't need to use the parameter inout

, but rather access the property memory

for outputValue

.

Note . I am using a generic keyPath @self

for the other side of my property mapping, so I can use this mapping for different classes that have a property downloadedOn

.

0


source







All Articles