objectForKey와 valueForKey의 차이점은 무엇입니까?


답변:


403

objectForKey:NSDictionary방법. 가 NSDictionary유사한 컬렉션 클래스입니다 NSArray대신 인덱스를 사용 제외하고는, 항목 구분하는 키를 사용합니다. 키는 제공하는 임의의 문자열입니다. 두 개의 객체가 동일한 키를 가질 수는 없습니다 (같은 객체의 NSArray색인을 가진 두 객체가없는 것처럼 ).

valueForKey:KVC 방법입니다. 모든 클래스에서 작동합니다. valueForKey:이름에 문자열을 사용하여 속성에 액세스 할 수 있습니다. 예를 들어, Account속성 이있는 클래스 가 있으면 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에 대해 더 자세히 알고 싶다면, 특히 Scott Stevenson의 블로그 에서 Google에 대한 많은 자습서가 있습니다 . NSKeyValueCoding 프로토콜 참조를 확인할 수도 있습니다 .

희망이 도움이됩니다.


12
valueForKey는 키가 @ 기호로 시작하는지 여부에 따라 NSDictionary 개체에 대해 다르게 동작합니다.
dreamlax 2016 년

61
objectForKey : 문자열뿐만 아니라 모든 객체를 키로 받아들입니다. 키가 NSCopying 프로토콜을 지원해야합니다.
Ashley Clark

5
valueForKey를 지적하여 아무도이 답변을 수정 한 사람이 아무도 없습니다. 기술적으로 해당 인스턴스 변수에 대한 액세스 권한을 부여하지 않고 인스턴스 변수를 관리 할 수있는 접근 자 메서드를 제공합니다.
Dany Joumaa

7
경고 : valueForKey는 현재 속도가 느릴 수 있습니다. 현재 iPad 앱의 주요 병목 현상이 있으므로 "표준"사전으로 바꾸면 앱이 눈에 띄게 빨라졌습니다. iOS의 KVC에 매우 잘못된 점이 있으며 성능 저하의 가치가 없으며 어쨌든 다시 작성 해야하는 다시는 사용하지 않을 것입니다. CALayers에서 NSString 키와 함께 NSString 키를 사용하고있었습니다. 인스트루먼트는 "CAObject_valueForKey"가 총 런타임 (!)의 25 % 인 것으로 나타났습니다
Adam

2
@Adam 무섭게 들린다. iOS7부터 다시 시도 했습니까? 그렇다면 이후에 변경 사항이 있습니까?
Unheilig

64

당신이 할 때 valueForKey:당신은 반면에,있는 NSString을 줄 필요가 objectForKey:열쇠 같은 NSObject의 서브 클래스를 취할 수 있습니다. 키-값 코딩의 경우 키는 항상 문자열이기 때문입니다.

실제로, 설명서 valueForKey:에는 NSString 을 제공하더라도 objectForKey:문자열이으로 시작하지 않는 한 @호출 [super valueForKey:]되지만 valueForUndefinedKey:예외가 발생할 수있는 호출 할 수 있다고 명시되어 있습니다.


당신이 의미하는 문서의 링크를 알려주십시오. 감사합니다.
Ali Amin

5
@ عليامين : 바로 여기 있습니다
dreamlax

20

여기에 사용하는 큰 이유 objectForKey:어디든지 대신 할 수 valueForKey:- valueForKey:알 수없는 키를 던질 것 NSUnknownKeyException"이 클래스는 키에 대한 코딩 호환 키 값이 아닙니다"말은.


5
알아두면 좋은 점 "valueForKey : 알 수없는 키를 사용하면"이 클래스는 키 값을 키 호환 코드가 아닙니다 "라는 NSUnknownKeyException이 발생합니다.
onmyway133

NSDictionary에서는 이것이 사실이 아니며 NSLog (@ "Z : % @", [@ {@ "X": @ (10), @ "Y": @ (20)} valueForKey : @ "Z"]); valueForKey는 지정된 키를 지원하지 않지만 NSDictionary 하위 클래스의 경우 다른 클래스에서 이러한 예외를 발생시킵니다.
Motti Shneor

13

말했듯이 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:모든 유형의 객체를 사용합니다.

의 값 objectForKey은 동일한 종류의 객체에 의해 액세스됩니다.


0

여기에 포괄적 인 답변을 제공하려고 노력할 것입니다. 많은 답변이 다른 답변에 나타나지만 각 답변이 불완전하고 일부 잘못되었습니다.

무엇보다도 objectForKey:NSDictionary반면, 방법 valueForKey:NSDictionary에 포함 - 어떤 KVC 불만 클래스의 필요한 KVC 프로토콜 방법입니다.

@dreamlax이 문서 힌트를 쓴 또한, 그것은 NSDictionary그 구현 valueForKey:방법 사용objectForKey:구현. 다시 말해서 [NSDictionary valueForKey:]호출합니다 [NSDictionary objectForKey:].

이것은 철저한 테스트를 통해 거대한 NSDictionary에 대한 수십억 건의 무작위 액세스를 통해 약 5 %에서 15 %의 차이를 내포하고 있음에도 불구하고 (동일한 입력 키 valueForKey:보다) 결코 빠를 수 없음을 objectForKey:의미합니다. 정상적인 상황에서 그 차이는 무시할 수 있습니다.

다음 : KVC 프로토콜은 NSString *키로 만 작동 하므로 다른 종류의 개체를 키로 사용할 수있는 반면 키 (또는 하위 클래스) valueForKey:만 허용 하므로 "낮은 수준" 은 복사 가능한 (NSCopying 프로토콜 호환) 개체를 허용합니다. 열쇠로.NSString *NSDictionaryobjectForKey:

마지막으로, 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);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.