NSDictionary 또는 NSMutableDictionary에 키가 있는지 확인하는 방법?


456

dict에 키가 있는지 확인해야합니다. 어떻게?


4
(여기서 인터넷을 검색하는 사람이라면 누구나 매우 오래된 질문 입니다. 아래의 SaintMacintosh 답변은 최신 기술이며,이 QA보다 5 년 앞서 있습니다. 도움이
되길 바랍니다

1
실제로 Andy Dent의 답변은 최신 기술과 더 많은 맥락을 제공합니다. 그리고 그것은 SaintMacintosh보다 일찍이 작업을 수행했습니다. 좀 더 아래로 스크롤하여 부탁하십시오.
Peter Kämpf

1
그는 다음을 사용합니다. keysByName [test]! = nil! = nil 검사는 중복되며 IMHO의 읽기가 어렵습니다. 구문을 찾는 사람들을 위해 TL; DR 버전을 공유하고 싶었습니다.
앤드류 후스

@SaintMacintosh에 동의합니다. 그의 대답은 훨씬 간결합니다.
Steve Schwarcz

당신이이 있는지 확인하려면 NSDictionary아무 키나 (비 특정)이 포함되어 사용한다 [dictionary allKeys].count == 0는 경우 count입니다 0에는 키가 없습니다 NSDictionary.
Aleksander Azizi

답변:


768

objectForKey 키가 없으면 nil을 반환합니다.


29
키가 존재하지만 해당 값이 nil이면 어떻게됩니까?
Fyodor Soikin

232
그건 불가능하다. NSDictionary에 nil을 추가 할 수 없습니다. [NSNull null]대신 사용해야 합니다.
Ole Begemann

10
@fyodor nil 값을 삽입하려고하면 nsdictionay가 NSInvalidArgumentException을 throw하므로 키가있는 경우는 없어야하지만 해당 값은 nil입니다.
Brad The App Guy

3
필요한 경우 objectForKey를 호출하므로 valueForKey를 사용하고 싶지 않습니까?
Raffi Khatchadourian

6
절대 절대 JSON 사전에 valueForKey를 사용하고 싶지는 않습니다. JSON은 모든 문자열을 키로 포함 수 있기 때문 입니다. 예를 들어, 키로 "@count"가 포함 된 경우 objectForKey : @ "@ count"는 올바른 값을 제공하지만 valueForKey : @ "@ count"는 키 / 값 쌍의 수를 제공합니다.
gnasher729

162
if ([[dictionary allKeys] containsObject:key]) {
    // contains key
}

또는

if ([dictionary objectForKey:key]) {
    // contains object
}

100
이 답변의 예 하나는 느립니다.
James Van Boxtel

5
읽는다 :이 답변의 예제 1은 O (1) 대신 불법 (O (n))으로 간주되어야합니다.
Hertzel Guinness

5
성능은 매우 관련이 있습니다. 이 정확한 라인이 관련이 없다는 것은 매우 사실 일 수 있지만 n 번 반복 될 경우 n * n을 복용하는 대신 갑자기 n이 걸리고 프로그램이 왜 느린 지 알 수 없습니다. 거의 모든 것이 한 번 또는 작은 경우에 빠릅니다. 그러나 프로그램이 잘못된 데이터 구조 (첫 번째 예에서 dict 대신 배열과 같은)를 사용함에 따라 비용이 많이 들게됩니다.
Andrew Hoos

2
키가 있는지 사전 (또는 세트)을 검사하면 O (n)이 최악 인 경우 O (1)이 예상됩니다. O (log (n))가 아닙니다. 애플의 문서는 이것을 명확하게 설명합니다.
Andrew Hoos

@JoeBlow “3D Mecanim 도트 애니메이션” Cocoa Touch / Objective-C와 Unity Engine / C #을 혼동하는 것처럼 들립니다. Unity 엔진이 실행되는 플랫폼에서 매우 비효율적이라는 것은 사실입니다. 그러나 Objective-C / Swift 애플리케이션이 본질적으로 비효율적이거나 대부분의 노련한 iOS 개발자가 코드의 효율성을 적극적으로 인식하지 못한다는 것은 전혀 사실이 아닙니다. 에 대해서는 "는 (4 거실) 성능 프로그래머에만 관련" - 당신은 명확 게임 개발자 아니에요. 배터리를 죽이지 않고 60FPS에서 훌륭한 그래픽 및 게임 플레이는 지속적인 도전입니다.
슬립 D. 톰슨

98

Objective-C 및 Clang의 최신 버전에는 다음과 같은 최신 구문이 있습니다.

if (myDictionary[myKey]) {

}

nil이 아닌 Objective-C 오브젝트 만 사전 (또는 배열)에 저장할 수 있으므로 nil과 동일한 지 검사 할 필요가 없습니다. 그리고 모든 Objective-C 객체는 진실한 가치입니다. 심지어 @NO, @0그리고 [NSNull null]참으로 평가합니다.

편집 : 스위프트는 이제 일입니다.

Swift의 경우 다음과 같은 것을 시도해보십시오.

if let value = myDictionary[myKey] {

}

이 구문은 myKey가 dict에 있고 if이면 값을 value 변수에 저장하는 경우에만 if 블록을 실행합니다. 이것은 0과 같은 잘못된 값에도 적용됩니다.


감사합니다! 궁금한 점이 있지만 objective-c 클래스 참조 developer.apple.com/library/mac/documentation/Cocoa/Reference/에 문서화 된이 동작을 찾을 수 없습니다 .
irh

2
당신은 장님이 아닙니다. 강조되지 않습니다. 그러나 여기 (clang)와 여기 (modern objc : very bottom)와 여기 (collection
guides

22
if ([mydict objectForKey:@"mykey"]) {
    // key exists.
}
else
{
    // ...
}

9

JSON 사전을 사용하는 경우 :

#define isNull(value) value == nil || [value isKindOfClass:[NSNull class]]

if( isNull( dict[@"my_key"] ) )
{
    // do stuff
}

8

나는 당신이 obj를 두 번 요구하더라도 Fernandes의 대답을 좋아합니다.

이것은 또한해야합니다 (마틴의 A와 다소 같음).

id obj;

if ((obj=[dict objectForKey:@"blah"])) {
   // use obj
} else {
   // Do something else like creating the obj and add the kv pair to the dict
}

Martin 과이 답변은 모두 iPad2 iOS 5.0.1 9A405에서 작동합니다.


5

방금 디버깅하는 데 약간의 시간을 낭비한 매우 불쾌한 한 가지-자동 완성 메시지를 사용 doesContain하여 작동하는 것처럼 보일 수 있습니다.

단, doesContain사용하는 해시 비교 대신 ID 비교를 사용 objectForKey하므로 문자열 키가있는 사전이 있으면 NO를 a에 반환합니다 doesContain.

NSMutableDictionary* keysByName = [[NSMutableDictionary alloc] init];
keysByName[@"fred"] = @1;
NSString* test = @"fred";

if ([keysByName objectForKey:test] != nil)
    NSLog(@"\nit works for key lookups");  // OK
else
    NSLog(@"\nsod it");

if (keysByName[test] != nil)
    NSLog(@"\nit works for key lookups using indexed syntax");  // OK
else
    NSLog(@"\nsod it");

if ([keysByName doesContain:@"fred"])
    NSLog(@"\n doesContain works literally");
else
    NSLog(@"\nsod it");  // this one fails because of id comparison used by doesContain

5

Swift를 사용하면 다음과 같습니다.

if myDic[KEY] != nil {
    // key exists
}

5

예. 이러한 종류의 오류는 매우 일반적이며 앱 충돌로 이어집니다. 따라서 다음과 같이 각 프로젝트에 NSDictionary를 추가하는 데 사용합니다.

//.h 파일 코드 :

@interface NSDictionary (AppDictionary)

- (id)objectForKeyNotNull : (id)key;

@end

//.m 파일 코드는 다음과 같습니다

#import "NSDictionary+WKDictionary.h"

@implementation NSDictionary (WKDictionary)

 - (id)objectForKeyNotNull:(id)key {

    id object = [self objectForKey:key];
    if (object == [NSNull null])
     return nil;

    return object;
 }

@end

코드에서는 다음과 같이 사용할 수 있습니다.

NSStrting *testString = [dict objectForKeyNotNull:@"blah"];

3

NSDictionary에서 키의 존재를 확인하려면 :

if([dictionary objectForKey:@"Replace your key here"] != nil)
    NSLog(@"Key Exists");
else
    NSLog(@"Key not Exists");

1
이것은 실제로이 기존의 대답 의 반복 일뿐 입니다.
Pang

3

nil은 Foundation 데이터 구조에 저장 될 수 없기 때문에 NSNull때때로를 나타냅니다 nil. NSNull단일 객체 이므로 NSNull직접 포인터 비교를 사용하여 값이 사전에 저장되어 있는지 확인할 수 있습니다 .

if ((NSNull *)[user objectForKey:@"myKey"] == [NSNull null]) { }

1
NSMutableArray를 키의 객체로 사용했을 때 작동하지 않았습니다.
pa12

4
왜 지구상에서이 문제가 제기 되었습니까? 그냥 잘못되었습니다. 싱글 톤 NSNull인스턴스가 사전에 키 값으로 저장된 경우이 확인은 true를 리턴합니다 @"myKey". 그것은 @"myKey"사전에 있지 않은 키와 완전히 다른 것 입니다. 실제로 두 가지는 상호 배타적입니다.
Mark Amery

이것은 여전히 ​​완전히 틀린 상태에서 여전히 5 표를 얻었으므로 Mark의 말만 반복 할 수 있습니다.
gnasher729

"완전히 잘못되었지만 흥미로운 정보를
가리킨다

이 답변은 수행 한 작업 (dict에서 NSNull 확인)과 수행하지 않는 작업 (dict에서 값 확인)을 명확하게하기 위해 편집되었습니다.
Andrew Hoos

2

신속한 4.2 솔루션

따라서 사전에 키가 포함되어 있는지 여부에 대한 질문에 대답하려면 다음을 요청하십시오.

let keyExists = dict[key] != nil

값을 원하고 사전에 키가 포함되어 있다는 것을 알고 있다면 다음과 같이 말합니다.

let val = dict[key]!

그러나 일반적으로 발생하는 것처럼 키에 키가 있는지 알지 못하는 경우 키를 가져 와서 사용하고 싶지만 존재하는 경우에만 다음과 같이 사용하십시오 if let.

if let val = dict[key] {
    // now val is not nil and the Optional has been unwrapped, so use it
}

1

조회 결과를 임시 변수에 저장하고 임시 변수가 nil인지 테스트 한 다음 사용하는 것이 좋습니다. 그렇게하면 같은 객체를 두 번 보지 않습니다.

id obj = [dict objectForKey:@"blah"];

if (obj) {
   // use obj
} else {
   // Do something else
}

1

Adirael이 objectForKey키 존재 여부를 확인 하도록 제안 했지만 objectForKeynullable 사전 을 호출하면 앱이 다운되어 다음과 같은 방식으로 수정했습니다.

- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
id object = dictionary;

if (dictionary && (object != [NSNull null])) {
    self.name = [dictionary objectForKey:@"name"];
    self.age = [dictionary objectForKey:@"age"];
}
return self;

}


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.