objectForKey
和 和有什么不一样valueForKey
?我在文档中查找了两者,它们对我来说似乎相同。
6 回答
objectForKey:
是一种NSDictionary
方法。AnNSDictionary
是一个类似于 an 的集合类NSArray
,除了不使用索引,它使用键来区分项目。密钥是您提供的任意字符串。没有两个对象可以具有相同的键(就像一个对象中没有两个对象NSArray
可以具有相同的索引)。
valueForKey:
是一种KVC方法。它适用于任何课程。valueForKey:
允许您使用字符串作为其名称来访问属性。因此,例如,如果我有一个Account
带有 property 的类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 看起来并不是那么有用。事实上,它看起来“罗嗦”。但是当你想在运行时改变一些东西时,你可以做很多很酷的事情,这些事情在其他语言中要困难得多(但这超出了你的问题范围)。
如果您想了解更多关于 KVC 的信息,如果您使用 Google 搜索,尤其是在Scott Stevenson 的博客中,有很多教程。您还可以查看NSKeyValueCoding 协议参考。
希望有帮助。
当你这样做时,valueForKey:
你需要给它一个 NSString,而objectForKey:
可以将任何 NSObject 子类作为键。这是因为对于键值编码,键始终是字符串。
实际上,文档指出,即使您提供valueForKey:
NSString,它仍会调用objectForKey:
,除非字符串以 开头@
,在这种情况下,它会调用[super valueForKey:]
,这可能valueForUndefinedKey:
会引发异常。
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:
将采用任何类型的对象。
in 中的值objectForKey
将被同种对象访问。
objectForKey
此表代表和之间的四个差异valueForKey
。
// |---------------------|-------------------------|------------------------|
// | | `objectForKey` | `valueForKey` |
// |---------------------|-------------------------|------------------------|
// | Works on ... | NSDictionary | NSDictionary / KVC |
// |---------------------|-------------------------|------------------------|
// | Throws exception | No | Yes (on KVC) |
// |---------------------|-------------------------|------------------------|
// | Feed | NSObject's subclass | NSString |
// |---------------------|-------------------------|------------------------|
// | Usage on KVC | cannot | can |
// |---------------------|-------------------------|------------------------|
我将尝试在这里提供一个全面的答案。很多点出现在其他答案中,但我发现每个答案都不完整,有些不正确。
首先也是最重要的,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);
}