objectForKey和valueForKey之間的區別?

objectForKeyvalueForKey什麼區別? 我在文檔中查看了它們,它們對我來講彷佛是同樣的。 dom


#1樓

當你執行valueForKey:你須要給它一個NSString,而objectForKey:能夠將任何NSObject子類做爲鍵。 這是由於對於鍵值編碼,鍵始終是字符串。 測試

事實上,文檔說明即便你給valueForKey:一個NSString,它也會調用objectForKey:不管如何,除非字符串以@開頭,在這種狀況下它會調用[super valueForKey:] ,這可能會調用valueForUndefinedKey:這可能會引起一個例外。 ui


#2樓

objectForKey:是一個NSDictionary方法。 NSDictionary是一個相似於NSArray的集合類,除了使用索引以外,它使用鍵來區分項目。 鍵是您提供的任意字符串。 沒有兩個對象能夠具備相同的密鑰(就像NSArray沒有兩個對象能夠具備相同的索引同樣)。 編碼

valueForKey:是一個KVC方法。 它適用於任何類。 valueForKey:容許您使用字符串做爲其名稱來訪問屬性。 例如,若是我有一個帶有屬性accountNumberAccount類,我能夠執行如下操做: spa

NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];

[newAccount setAccountNumber:anAccountNUmber];

NSNumber *anotherAccountNumber = [newAccount accountNumber];

使用KVC,我能夠動態訪問該屬性: .net

NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];

[newAccount setValue:anAccountNumber forKey:@"accountNumber"];

NSNumber *anotherAccountNumber = [newAccount valueForKey:@"accountNumber"];

這些是等同的陳述。 code

我知道你在想:哇,可是諷刺。 KVC看起來並不那麼有用。 事實上,它看起來「羅嗦」。 可是當你想在運行時改變一些東西時,你能夠作不少很酷的事情,這些事情在其餘語言中要困可貴多(但這超出了你的問題的範圍)。 orm

若是你想了解更多關於KVC的信息,那麼若是你特別在Scott Stevenson的博客上有 Google的話,那麼有許多教程。 您還能夠查看NSKeyValueCoding協議參考對象

但願有所幫助。 教程


#3樓

這裏有一個很好的理由使用objectForKey:儘量代替valueForKey: - valueForKey:用未知的密鑰將拋出NSUnknownKeyException說:「這個類不是鍵值編碼兼容的關鍵」。


#4樓

如上所述, objectForKey: datatype是:(id)aKeyvalueForKey: datatype是:(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的值將由同一種對象訪問。


#5樓

我會盡力在這裏提供一個全面的答案。 不少要點出如今其餘答案中,但我發現每一個答案都不完整,有些不正確。

首先, objectForKey:是一個NSDictionary方法,而valueForKey:是任何KVC投訴類所需的KVC協議方法 - 包括NSDictionary。

此外,正如@dreamlax所寫,文檔提示NSDictionary實現其valueForKey:方法使用objectForKey:實現。 換句話說 - [NSDictionary valueForKey:]調用[NSDictionary objectForKey:]

這意味着, valueForKey:永遠不會比objectForKey:更快objectForKey:在相同的輸入鍵上)雖然完全的測試我已經暗示了大約5%到15%的差別,超過數十億隨機訪問一個巨大的NSDictionary。 在正常狀況下 - 差別能夠忽略不計。

下一步:KVC協議僅適用於NSString *鍵,所以valueForKey:只接受NSString * (或子類)做爲鍵,而NSDictionary能夠做爲鍵使用其餘類型的對象 - 這樣「低級」 objectForKey:接受任何可複製(符合NSCopying協議)對象做爲密鑰。

最後, NSDictionary's valueForKey: NSDictionary's實現valueForKey:偏離了KVC文檔中定義的標準行爲,而且不會爲它找不到的鍵發出NSUnknownKeyException - 除非這是一個「特殊」鍵 - 以'@'開頭的 -一般意味着一個「聚合」功能鍵(例如@"@sum, @"@avg" )。相反,當在NSDictionary中找不到鍵時它只返回一個nil - 表現與objectForKey:相同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);
}
相關文章
相關標籤/搜索