I have created a category on NSDictionary
in order to make a copy, with a certain fixed modification applied to all keys (to use when mapping my objects against a web service):
@implementation NSDictionary (TransformKeys)
- (NSDictionary*) dictionaryByTransformingKeysWithBlock:(NSString* (^)(NSString* key))block
{
NSMutableDictionary* transformedDictionary = [NSMutableDictionary new];
for(NSString* key in [self allKeys]){
// Transform the key string:
NSString* transformedKey = block(key);
// Copy value, using modified key in target dictionary:
[transformedDictionary setObject:[self objectForKey:key]
forKey:transformedKey];
}
return transformedDictionary;
}
@end
So I can map (say) @{ @"userName" : @"John"}
to {@"UserName" : @"John"}
To use as part of said key transformations, I have also defined a category on NSString
to raise the case of the first character:
@implementation NSString (Camel)
- (NSString*) stringByCapitalizingFirstCharacter
{
if ([self length] == 0){
return @"";
}
NSString* firstCharacter = [self substringToIndex:1];
firstCharacter = [firstCharacter uppercaseString];
if ([self length] == 1) {
return firstCharacter;
}
NSString* theRest = [self substringFromIndex:1];
return [firstCharacter stringByAppendingString:theRest];
}
@end
The keys, of course, are the object's property names obtained by introspection from the Objective-C runtime.
When I print to the console my dictionary -or its allKeys
array, doesn't matter- using NSLog()
, some of the keys are enclosed in quotation marks, while others are printed as-is.
The immediate cause seems to be that I am transforming my dictionary keys following two different rules, and they somehow print differently:
If I transform my keys by capitalizing the first character, they print as-is:
NSDictionary* convertedDictionary = [dictionary dictionaryByTransformingKeysWithBlock:^NSString *(NSString *key) {
return [key stringByCapitalizingFirstCharacter];
}];
// -> Dictionary keys are printed to console as-is; i.e. UserName
If I transform my keys by capitalizing and then appending a suffix, they are print enclosed in double quotation marks:
NSDictionary* convertedDictionary = [dictionary dictionaryByTransformingKeysWithBlock:^NSString *(NSString *key) {
NSString* capitalized = [key stringByCapitalizingFirstCharacter];
return [capitalized stringByAppendingString:@"__c"];
}];
// -> Dictionary keys are printed to console in quotation marks; i.e. "UserName"
I'm sure it's just a logging artifact, and the actual strings do not contain "
in them, but it is a bit annoying.
Is there a way to unify the display of all keys in the console? Am I missing something?
I converted my dictionary to JSON (which is what I'll ultimately end up doing, anyway) and tried logging that instead:
NSData* data = [NSJSONSerialization dataWithJSONObject:[dictionary allKeys]
options:NSJSONWritingPrettyPrinted
error:nil];
NSLog(@"Keys: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
Now all the keys are uniformly enclosed in quotation marks (as expected), so this confirms that internally my data is in the expected format and no problems should arise due to the discrepancy observed in the log...
Although I cannot back this up with any documentation, from a quick test and a lot of time spending looking at logs, it seems that any key that contains non-alphanumeric characters (including spaces) will be logged with double quotes (and that's why you get it with your __
suffix)
So, this:
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
@autoreleasepool {
NSDictionary *dict = @{
@"simple": @"",
@"camelCase": @"",
@"camelCaseWith__suffix": @"",
@"camelCaseWith space": @"",
@"camelCaseWith/special": @""
};
NSLog(@"%@", dict);
}
}
would log:
{
camelCase = "";
"camelCaseWith space" = "";
"camelCaseWith/special" = "";
"camelCaseWith__suffix" = "";
simple = "";
}