답변:
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 *
NSDictionary
objectForKey:
마지막으로, 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);
}