Я согласен с большинством ответов, что NSDictionary
должен быть доступен с помощью objectForKey:
или аналогичными методами. Однако можно разрешить доступ к точкам нотации к NSDictionary
, и для учебных целей это может быть интересно для кого-то. Также, когда вы, например, получаете большие словари JSON через AFNetworking
, этот метод может облегчить доступ и читаемость вашего кода.
Это мое решение:
DictionaryProperties.h: (класс обертывание NSDictionary для доступа к свойству)
@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: (класс объявление внутри словаря)
#import "DictionaryProperties.h"
@interface ExampleDictContent : DictionaryProperties
@property (strong, nonatomic) NSString* someData;
@property (strong, nonatomic) NSString* someOtherData;
@end
@implementation ExampleDictContent
@end
Использование: (простая декларация словаря, выделение обертки и доступ к свойству)
#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);
Это будет печатать:
someData content
someOtherData content
Так в основном DictionaryProperties
работы в качестве фасада для доступа к NSDictionary
. Он использует forwardInvocation
для преобразования метода вызова get-property
в вызов getObjectForKey:
по словарю. Что мне нравится в этом, так это то, что он позволяет автозаполнение словаря, а также позволяет явным образом объявлять, какие ключи я хочу получить (в файле ExampleDictContent.h
). Обратите внимание, что это решение не позволяет писать права доступа к свойствам, но может быть добавлено, как показано в приведенной ниже ссылке.
Это решение частично вдохновлено karstenlitsche's solution. Основное отличие состоит в том, что это решение основано на подклассификации вместо категорий.
Дайте мне несколько минут, я сделаю что-то, что позволит вам использовать точечную нотацию, используя категорию. –
@ RichardJ.RossIII Я не думаю, что вы должны отвечать категорией. Это демонстрирует некоторые возможности Obj-C, но для этого было бы довольно плохой практикой. Возможно, лучшим вариантом будет предложить объект модели, который является подклассом «NSObject». –
Я сомневаюсь, что вы можете что-то сделать с перезаписью '- (id) valueForUndefinedKey:' поскольку компилятор отклонит точку ... – JustSid