Answers:
objectForKey:
是一种NSDictionary
方法。An NSDictionary
是类似于的集合类NSArray
,除了不使用索引,它使用键来区分项目。密钥是您提供的任意字符串。任何两个对象都不能具有相同的键(就像一个对象中NSArray
不能有相同的索引一样)。
valueForKey:
是一种KVC方法。它适用于ANY类。valueForKey:
允许您使用字符串作为属性来访问属性。因此,例如,如果我有一个Account
带有属性的类accountNumber
,则可以执行以下操作:
NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];
[newAccount setAccountNumber:anAccountNUmber];
NSNumber *anotherAccountNumber = [newAccount accountNumber];
使用KVC,我可以动态访问属性:
NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];
[newAccount setValue:anAccountNumber forKey:@"accountNumber"];
NSNumber *anotherAccountNumber = [newAccount valueForKey:@"accountNumber"];
这些是等效的语句集。
我知道您在想:哇,但是讽刺地。KVC看起来并没有那么有用。实际上,它看起来很“罗word”。但是,当您想在运行时进行更改时,您可以做很多很酷的事情,而在其他语言中,这要困难得多(但这超出了您的问题范围)。
如果您想了解有关KVC的更多信息,那么如果您有Google的话,可以找到很多教程,特别是在Scott Stevenson的博客上。您也可以签出《NSKeyValueCoding协议参考》。
希望能有所帮助。
这是一个objectForKey:
尽可能使用而不是使用它的重要原因valueForKey:
- valueForKey:
带有未知密钥会抛出NSUnknownKeyException
“该类不符合该密钥的编码值”。
如前所述,objectForKey:
数据类型为,:(id)aKey
而valueForKey:
数据类型为:(NSString *)key
。
例如:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:@"123"],[NSNumber numberWithInteger:5], nil];
NSLog(@"objectForKey : --- %@",[dict objectForKey:[NSNumber numberWithInteger:5]]);
//This will work fine and prints ( 123 )
NSLog(@"valueForKey : --- %@",[dict valueForKey:[NSNumber numberWithInteger:5]]);
//it gives warning "Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'" ---- This will crash on runtime.
因此,valueForKey:
将仅采用字符串值,并且是KVC方法,而objectForKey:
将采用任何类型的对象。
中的值objectForKey
将由相同类型的对象访问。
我将在这里尝试提供全面的答案。许多要点都出现在其他答案中,但是我发现每个答案都不完整,有些不正确。
首先objectForKey:
是一种NSDictionary
方法,而valueForKey:
任何KVC投诉类别(包括NSDictionary)都需要KVC协议方法。
此外,正如@dreamlax所写,文档暗示了使用其实现来NSDictionary
实现其valueForKey:
方法。换句话说- 呼吁objectForKey:
[NSDictionary valueForKey:]
[NSDictionary objectForKey:]
。
这意味着,它valueForKey:
永远不可能比objectForKey:
(在相同的输入键)虽然彻底的测试我做过暗示约5%至15%的差异,在数十亿的随机访问到一个巨大的NSDictionary。在正常情况下-差异可以忽略不计。
下一页:KVC协议仅适用于NSString *
密钥,因此valueForKey:
将仅接受NSString *
(或子类)作为密钥,而NSDictionary
可以与其他类型的对象作为密钥一起使用-以便“较低级别” objectForKey:
接受任何可复制的对象(符合NSCopying协议的对象)作为关键。
最后,NSDictionary's
实施的valueForKey:
行为会偏离KVC文档中定义的标准行为,并且不会NSUnknownKeyException
为找不到的密钥发出-除非这是一个“特殊”密钥-以“ @”开头的密钥(通常表示“聚合”功能键(例如@"@sum, @"@avg"
)。相反,当在NSDictionary中找不到密钥时,它将仅返回nil,其行为与objectForKey:
以下是一些测试代码来演示和证明我的笔记。
- (void) dictionaryAccess {
NSLog(@"Value for Z:%@", [@{@"X":@(10), @"Y":@(20)} valueForKey:@"Z"]); // prints "Value for Z:(null)"
uint32_t testItemsCount = 1000000;
// create huge dictionary of numbers
NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:testItemsCount];
for (long i=0; i<testItemsCount; ++i) {
// make new random key value pair:
NSString *key = [NSString stringWithFormat:@"K_%u",arc4random_uniform(testItemsCount)];
NSNumber *value = @(arc4random_uniform(testItemsCount));
[d setObject:value forKey:key];
}
// create huge set of random keys for testing.
NSMutableArray *keys = [NSMutableArray arrayWithCapacity:testItemsCount];
for (long i=0; i<testItemsCount; ++i) {
NSString *key = [NSString stringWithFormat:@"K_%u",arc4random_uniform(testItemsCount)];
[keys addObject:key];
}
NSDictionary *dict = [d copy];
NSTimeInterval vtotal = 0.0, ototal = 0.0;
NSDate *start;
NSTimeInterval elapsed;
for (int i = 0; i<10; i++) {
start = [NSDate date];
for (NSString *key in keys) {
id value = [dict valueForKey:key];
}
elapsed = [[NSDate date] timeIntervalSinceDate:start];
vtotal+=elapsed;
NSLog (@"reading %lu values off dictionary via valueForKey took: %10.4f seconds", keys.count, elapsed);
start = [NSDate date];
for (NSString *key in keys) {
id obj = [dict objectForKey:key];
}
elapsed = [[NSDate date] timeIntervalSinceDate:start];
ototal+=elapsed;
NSLog (@"reading %lu objects off dictionary via objectForKey took: %10.4f seconds", keys.count, elapsed);
}
NSString *slower = (vtotal > ototal) ? @"valueForKey" : @"objectForKey";
NSString *faster = (vtotal > ototal) ? @"objectForKey" : @"valueForKey";
NSLog (@"%@ takes %3.1f percent longer then %@", slower, 100.0 * ABS(vtotal-ototal) / MAX(ototal,vtotal), faster);
}