354 Stimmen

Unterschied zwischen objectForKey und valueForKey?

Was ist der Unterschied zwischen objectForKey y valueForKey ? Ich habe in der Dokumentation nachgeschaut, und sie scheinen mir gleich zu sein.

1voto

Motti Shneor Punkte 1972

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);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X