Was ist der Unterschied zwischen objectForKey
y valueForKey
? Ich habe in der Dokumentation nachgeschaut, und sie scheinen mir gleich zu sein.
Antwort
Zu viele Anzeigen?Ich werde versuchen, hier eine umfassende Antwort zu geben. Viele der Punkte finden sich in anderen Antworten, aber ich fand jede Antwort unvollständig und einige falsch.
Zuallererst, objectForKey:
ist ein NSDictionary
Methode, während valueForKey:
ist eine KVC-Protokollmethode, die von jeder KVC-Beschwerdeklasse benötigt wird - einschließlich NSDictionary.
Außerdem, wie @dreamlax schrieb, weist die Dokumentation darauf hin, dass NSDictionary
implementiert seine valueForKey:
Methode VERWENDUNG seine objectForKey:
Umsetzung. Mit anderen Worten. [NSDictionary valueForKey:]
Aufforderungen [NSDictionary objectForKey:]
.
Dies bedeutet, dass valueForKey:
kann niemals schneller sein als objectForKey:
(auf der gleichen Eingabetaste), obwohl gründliche Tests, die ich durchgeführt habe, einen Unterschied von etwa 5 bis 15 % ergeben, und zwar bei Milliarden von Zufallszugriffen auf ein riesiges NSDictionary. In normalen Situationen - der Unterschied ist vernachlässigbar.
Weiter: Das KVC-Protokoll funktioniert nur mit NSString *
Tasten, daher valueForKey:
akzeptiert nur eine NSString *
(oder Unterklasse) als Schlüssel, während NSDictionary
mit anderen Arten von Objekten als Schlüssel arbeiten kann - so dass die "untere Ebene" objectForKey:
akzeptiert jedes kopierfähige (mit dem NSCopying-Protokoll konforme) Objekt als Schlüssel.
Zuletzt, NSDictionary's
Umsetzung von valueForKey:
weicht vom Standardverhalten ab, das in der KVC-Dokumentation definiert ist, und gibt NICHT eine NSUnknownKeyException
für einen Schlüssel, den es nicht finden kann - es sei denn, es handelt sich um einen "speziellen" Schlüssel, der mit '@' beginnt, was in der Regel ein "Aggregations"-Funktionsschlüssel ist (z. B. @"@sum, @"@avg"
). Stattdessen wird einfach ein Nullwert zurückgegeben, wenn ein Schlüssel nicht im NSDictionary gefunden wird - dies entspricht dem Verhalten von objectForKey:
Nachfolgend finden Sie einige Testcodes, um meine Anmerkungen zu demonstrieren und zu belegen.
- (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);
}
- See previous answers
- Weitere Antworten anzeigen