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);
}
相关文章
相关标签/搜索