一个库,可以将一个 NSDictionary 映射到另一个,可以一次性映射键和值。它还允许您将数据的任何一种表示格式化与另一种表示(例如,rest api -> 内部模型表示)解耦。
在尝试提供尽可能多的自定义的情况下,这个小巧的库做出了极少的假设,这意味着您必须相当详细。但请参阅便利方法,这些方法应大大减少较简单情况的代码。
(提示:使用 Cocoapods)
将 KVMapper
文件夹的内容拖放到 Xcode 您最喜欢的 IDE 中。
您有一个从 JSON Rest API 获取的字典,给出猫的名字和它们的年龄:NSDictionary 表示看起来像这样
NSDictionary *catsFromAPI=@{
@"maggy_the_ninja": @5,
@"magrat_the_rockstar": @6,
@"mable_the_wizard": @2,
… 15 or so more cats
@"milly_the_scratcher":@"3"
};
您想要一个看起来像这样的 NSDictionary
//llamaCaseCatNames
//ages are now in human years (sort of)
NSDictionary *catsForMyModel=@{
@"maggyTheNinja": @30,
@"magratTheRockstar": @36,
@"mableTheWizard": @12,
… 15 or so more cats
@"millyTheScratcher":@"3"
};
这样您就可以做到这一点
#import "KVMapper.h"
#import "Transformers.h" //see apendix, used to do snake_case to llameCase transformation
NSDictionary *catsMappingDict=[KVMapper mappingDictionaryForKeys:catsFromAPI.allKeys
defaultKeyTransformer:^NSString *(NSString *catName) {
return [Transformers snakeToLlamaCase:catName];
}
defaultValueTransformer:^id(NSNumber *catAge) {
float humanAge=catAge.floatValue+5;
return [NSNumber numberWithFloat:humanAge];
}];
NSDictionary *catsForMyModel=[KVMapper mappedDictionaryWithInputDictionary:catsFromAPI mappingDictionary:catsMappingDict];
//catsForMyModel is now as in the form @{@"maggyTheNinja": @30, …… etc.}
要从字典创建一个字典,您需要 mappedDictionaryWithInputDictionary:mappingDictionary:
啰嗦一些
+(NSDictionary *)mappedDictionaryWithInputDictionary:(NSDictionary *)inputDict mappingDictionary:(NSDictionary *)mappingDict;
NSDictionary *myMappedDictionary=[KVMapper mappedDictionaryWithInputDictionary:inputDict mappingDictionary:mappingDict];
这个函数接收您的输入字典和一个 映射字典。
映射字典是一个 NSDictionary,其键对应于输入字典的键,值是 KVMap
的实例。
KVMap
对象只是一个有两个属性的 NSObject
keyTransformationBlock
valueTransformationBlock
前者接收并返回一个 NSString
(键),后者接收并返回 id
即您想要的对象(值)。
制作一个 KVMap
与设置键和值转换块一样简单
KVMap *myKVMap=[[KVMap alloc] init];
myKVMap.keyTransformationBlock=^(NSString *inputString){
return [inputString lowercaseString];
};
myKVMap.valueTransformationBlock=^(id *input){
return @5;
};
有一个初始化器 initWithKeyTransformationBlock:valueTransformationBlock:
用一步创建一个。
要创建映射字典,您必须创建所需的 various KVMaps 来将输入字典的键值对映射成期望的形式。然后将这些映射作为键对应到输入字典的键。
// the input dictionary
NSDictionary *inputDict=@{
@"KEYONE":@1,
@"KEYTWO":@2,
@"myKEYTHREE":@"3",
};
//set up maps (you can use the same map if it applies to multiple KV pairs)
KVMap *myKeyOneAndTwoKVMap=[[KVMap alloc] init];
myKeyOneAndTwoKVMap.keyTransformationBlock=^(NSString *inputString){
return [NSSString stringWithFormat:@"my%@",[inputSting lowerCaseString]];
};
myKeyOneAndTwoKVMap.valueTransformationBlock=^(id *input){
return [NSString stringWithFormat:@"%i",input];
};
KVMap *myKeyThreeKVMap=[[KVMap alloc] init];
myKeyThreeKVMap.keyTransformationBlock=^(NSString *inputString){
return [inputSting lowerCaseString];
};
//create mapping dict
NSDictionary *mappingDict=@{
@"KEYONE":myKeyOneAndTwoKVMap,
@"KEYTWO":myKeyOneAndTwoKVMap,
@"myKEYTHREE":myKeyThreeKVMap
};
// [KVMapper mappedDictionaryWithInputDictionary:inputDict mappingDictionary:mappingDict];
// will return:
// @{
// @"mykeyone":@"1",
// @"mykeytwo":@"2",
// @"mykeythree":@"3"
// };
编写所有的映射逻辑很快就会变得乏味,尤其是在我们经常需要对键、值或两者进行相同转换的情况下。
所以 KVMapper 有:KVMapsForKeys:defaultKeyTransformer:
和 KVMapsForKeys:defaultKeyTransformer:defaultValueTransformer:
例如,如果我们想创建一个映射字典,其中所有的键都转换成小写,而所有的值(以字符串形式获取)都是 NSURL。
NSDictionary *mappingDict=[KVMapper mappingDictionaryForKeys:testDict.allKeys
defaultKeyTransformer:^(NSString *inKey){
return [Transformers snakeToLlamaCase:inKey];
}
defaultValueTransformer:^(id inValue){
NSURL *url=[NSURL URLWithString:inValue];
return url;
}];
现在可以使用这个 mappingDict
进行操作。
//Transformers.h
#import <Foundation/Foundation.h>
@interface Transformers : NSObject
+(NSString *)snakeToLlamaCase:(NSString *)inKey;
@end
//Transformers.m
#import "Transformers.h"
@implementation Transformers
#pragma mark -string transformers
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"couldn't set value: %@ for undefkey:%@",[value description],key);
}
+(NSString *)snakeToLlamaCase:(NSString *)inKey{
NSArray *keyComponents=[inKey componentsSeparatedByString:@"_"];
return [self llamaCasFromComponents:keyComponents];
}
+(NSString *)llamaCasFromComponents:(NSArray *)components{
NSMutableString *llamaCaseString=[NSMutableString string];
for (NSString *component in components) {
NSString *firstLetterUpper=[[component substringToIndex:1] uppercaseString];
NSString *restOfComponent=[component substringFromIndex:1];
NSString *newComponent=[NSString stringWithFormat:@"%@%@",firstLetterUpper,restOfComponent];
[llamaCaseString appendString:newComponent];
}
NSString *firstLetterLower=[[llamaCaseString substringToIndex:1] lowercaseString];
[llamaCaseString replaceCharactersInRange:NSMakeRange(0, 1) withString:firstLetterLower];
return llamaCaseString;
}
@end
MIT
欢迎!!
永恒的感谢