有没有办法通过点表示法来访问像这样的NSDictionary中的键值?
NSDictionary *returnVal = [NSDictionary dictionaryWithObjectsAndKeys:@"Saturn", @"name", @"Gas Giant", @"type", nil];
NSLog(@"VALUE: %@", [returnVal valueForKey:@"name"]); // This is how I am doing it now.
NSDictionary
没有点语法,但应考虑使用objectForKey:
而不是valueForKey:
不是,不是。
点表示法是使用该选择器名称调用方法的简便方法。换句话说,这......
NSLog(@"Hello, %@", foo.bar.name);
......跟这个一样......
NSLog(@"Hello, %@", [[foo bar] name]);
当我说“相同”时,我的意思是它们被编译成相同的代码。这只是语法糖。
一个普通的NSDictionary不会这样做。您可以使用键值编码来伪装它,它可以让您调用valueForKeyPath
来获取这样的属性:
NSLog(@"Hello, %@", [foo valueForKeyPath:@"bar.name"]);
但是,如果您真的希望能够在代码中编写foo.bar.name
,那么您必须创建一个覆盖forwardInvocation:
的自定义类;这可以让你捕获一个未知的消息给一个对象,并用它做其他事情,除了抛出一个错误。在这种情况下,您可以将未知选择器更改为它包含的NSDictionary实例上的查找。
但即使您这样做,编译器仍可能会生成警告,除非您创建了声明这些属性名称的头文件。
我同意NSDictionary
应该使用objectForKey:
或类似方法访问的大多数答案。然而,有可能允许点符号访问NSDictionary
,并且出于学习目的,这可能对某人有趣。此外,例如,当您通过AFNetworking
检索大型JSON字典时,此方法可以简化代码的访问和可读性。
这是我的解决方案:
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的启发。主要区别在于此解决方案基于子类而不是类别。
不,我不这么认为。
从参考手册。
Accessing Keys and Values
– allKeys
– allKeysForObject:
– allValues
– getObjects:andKeys:
– objectForKey:
– objectsForKeys:notFoundMarker:
– valueForKey:
这被列为访问密钥和值的唯一方法。所以你做得很好。
如果密钥是公共属性并且可读,则可以访问它。
您提到的访问字典元素的方式是理想的方式(使用键)。如果你想做别的事,也许你可以用 -
NSArray *allValues = [returnVal allValues];
现在使用此数组也可以执行任务。如果你想要一些特定的东西然后提一下,可能是因为可以有其他方式。
此外,由于NSDictionary类不会定义任何属性,因此点符号是不可能的。
不,你正在以正确的方式做到这一点。在iOS世界中,通常正确的方法是唯一的方法。 :)
如果你真的想要点符号(以及你用类型对象获得的其他好东西),你将不得不将字典表示填充到一个对象中。最常见的是我的界面如下所示:
@interface FooBar : NSObject {
NSString *someData;
int someNumber;
}
@property (nonatomic, copy) NSString *someData;
@property (nonatomic, assign) int someNumber;
+ (FooBar *)FooBarFromDictionary:(NSDictionary *)dataDict;
@end
实施应该清楚。然后你可以
FooBar *fb = [FooBar FooBarFromDictionary:data];
NSLog(@"fb.someData = %@", fb.someData);
从技术上讲,你可以这样做:
typedef id (^valueBlock)(id);
@interface NSDictionary(dotNotationAddons)
@property(nonatomic, readonly) valueBlock value;
@end
@implementation NSDictionary(dotNotationAddons)
-(valueBlock) value
{
return [[^(id key) {
return [self objectForKey:key];
} copy] autorelease];
}
@end
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"One", @"2", @"Two", @"3", @"Three", @"4", @"Four", nil];
id value = dictionary.value(@"One");
NSLog(@"%@", value);
}
return 0;
}
我不知道你是否正在寻找,但我希望它有所帮助!
答案仍然没有,但你可以使用速记
myDictionary[@"key"]
代替
[myDictionary objectForKey:@"key"]