[objective-c] objectForKey와 valueForKey의 차이점은 무엇입니까?

차이점은 무엇이며 objectForKey그리고 valueForKey? 나는 문서에서 둘 다를 보았고 그들은 나에게 똑같이 보였다.



답변

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 프로토콜 참조를 확인할 수도 있습니다 .

희망이 도움이됩니다.


답변

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

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


답변

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


답변

말했듯이 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은 동일한 종류의 객체에 의해 액세스됩니다.


답변

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

무엇보다도 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);
}


답변