3

我正在使用 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];

但是当我这样做时,代码不会编译。它说“在 'RKAttributeMapping *' 类型的对象上找不到属性 valueTransformer”。我不明白这一点。我在互联网上看到的所有示例,包括带有RestKit 文档的示例,都说了同样的话。所有示例都设置对象的valueTransformer属性AttributeMapping。甚至RestKit 类参考也说我可以设置它。但是为什么它不编译呢?

4

3 回答 3

2

所以我终于设法找出问题所在。

我的 podfile 配置为使用 RestKit 0.20.3。然后我添加RKValueTransformers了另一个 Pod。但是,RestKit 0.20.3 和更早版本带有他们自己版本的 RKValueTransformer(.h 和 .m)文件。并且那些旧版本的 RestKit 不支持添加您自己的 Transformer,因为它不使用较新的RKValueTransformers库。

当我将我的 RestKit 版本升级到最新版本时(实际上任何高于 0.21.0 的版本都可以),一切都开始正常了。我不需要添加 pod RKValueTransformers,因为它会自动添加为 RestKit 的依赖项。

于 2014-11-12T22:55:22.080 回答
1

查看使用insertValueTransformer:atIndex:而不是,addValueTransformer:以便您可以将其添加到列表的开头而不是结尾。

于 2014-11-12T22:13:35.807 回答
0

很快,我就可以成功地创建一个价值转换器。它的目的是为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

注意:我@self为我的属性映射的另一端使用了一个通用的 keyPath,以便我可以将此映射用于具有该downloadedOn属性的各种类。

于 2016-01-30T10:18:45.997 回答