I agree with most of the answers NSDictionary should NSDictionary with objectForKey: or similar methods. However, you can allow access to the notation points to NSDictionary , and for training this may be interesting for someone. Also, when you, for example, get large JSON dictionaries through AFNetworking , this method can facilitate the access and readability of your code.
This is my decision:
DictionaryProperties.h: (a class that carries an NSDictionary for accessing properties)
@interface DictionaryProperties : NSObject{ NSMutableDictionary* _backingDict; } @property (nonatomic, strong) NSMutableDictionary* backingDict; + (DictionaryProperties*) allocWithDictionary:(NSDictionary*)dict; @end
DictionaryProperties.m:
#import "DictionaryProperties.h" @implementation DictionaryProperties @synthesize backingDict = _backingDict; - (id) initWithDictionary:(NSDictionary*)dict { if (self) { if ([dict isKindOfClass:[NSMutableDictionary class]]) { self.backingDict = (id)dict; } else { self.backingDict = [[NSMutableDictionary alloc] initWithDictionary:dict]; } } return self; } + (DictionaryProperties*) allocWithDictionary:(NSDictionary*)dict { return [[DictionaryProperties alloc] initWithDictionary:dict]; } - (void)forwardInvocation:(NSInvocation *)invocation { NSString* key = NSStringFromSelector(invocation.selector); invocation.selector = @selector(objectForKey:); [invocation setArgument:&key atIndex:2]; if ([self.backingDict objectForKey:key]) { [invocation invokeWithTarget:self.backingDict]; } else { [self doesNotRecognizeSelector:invocation.selector]; } } - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{ return [self.backingDict methodSignatureForSelector:@selector(objectForKey:)]; } @end
ExampleDictContent.h: (class declaring what is inside the dictionary)
#import "DictionaryProperties.h" @interface ExampleDictContent : DictionaryProperties @property (strong, nonatomic) NSString* someData; @property (strong, nonatomic) NSString* someOtherData; @end @implementation ExampleDictContent @end
Usage: (simple dictionary declaration, shell distribution, and access to properties)
#import "ExampleDictContent.h" NSDictionary* d = [NSDictionary dictionaryWithObjects:NSArray arrayWithObjects:@"someData content", @"someOtherData content", nil forKeys:NSArray arrayWithObjects:@"someData", @"someOtherData", nil]; ExampleDictContent* dictWProps = [ExampleDictContent allocWithDictionary:d]; NSLog(dictWProps.someData); NSLog(dictWProps.someData);
This will print:
someData content someOtherData content
Thus, basically DictionaryProperties acts as a facade for accessing NSDictionary . It uses forwardInvocation to convert a call to the get-property method to a call to getObjectForKey: in the dictionary. I like the fact that it allows autocompletion of the dictionary, and also allows you to explicitly declare which keys I want to receive (in the ExampleDictContent.h file). Please note that this solution does not allow write access to properties, but can be added as shown in the link below.
This solution is partly inspired by the karstenlitsche solution . The main difference is that this decision is based on subclassification instead of categories.