読者です 読者をやめる 読者になる 読者になる

NSDictionaryから取り出したValueの型を判断するの巻(NSNumber)

NSDictionaryに bool or int を入れた場合、NSNumberに変換して入れると思いますが、 これを今度取り出す時にそれが元々 bool or int なのかを判断するのに手間取ったので備忘録を記載しておきます。

入れる時と取り出す時をこちらでハンドリングできれば、時に問題もないのですが、 SDKなどを作っている時に、アプリが何を指定してくるかわからない時などに使えます。

通常のNSDictionaryの使い方をおさらい
// 入れる時
NSDictionary *newDic = @{@"key1":@"String",
                        @"key2":@YES,  // bool
                        @"key3":@0]};  // int

// 取り出し方
NSString *string = newDic[@"key1"];
BOOL bool = [[newDic objectForKey:@"key2"] boolValue];
NSInteger int = [[NewDic objectForKey:@"key3"] integerValue];

ただこの場合key2がbool であるということがわかっていることが前提です。 例えばkey2は、取り出し方によって 下記両方とも正常に働いてしまいます。key3も場合も同じ

BOOL bool = [[newDic objectForKey:@"key2"] boolValue];  // YES
NSInteger int = [[NewDic objectForKey:@"key2"] integerValue];  // 1
だがしかし

例えば、取り出した時にtrueを元々入れていた場合は文字列の"true"に変更
0を入れていた場合は文字列の"0"に変更をしたい場合など、
どうしても元々の型を判別したいです。

などの場合に困った。

[neDic valueForKey:key2] isKindOfClass:[NSString class]
[neDic valueForKey:key2] isKindOfClass:[NSNumber class]

こんな感じでclassを判断してもyes or 1 は、両方NSNumber classだし、

[newDic valueForKey:key2] isEqualToNumber:@YES])

こんな感じで判断しても、結局意味をなしていない(やりたい判断はできない)
結果 これで解決
- (BOOL) isBoolNumber:(NSNumber *)num {
   CFTypeID boolID = CFBooleanGetTypeID();
   CFTypeID numID = CFGetTypeID((__bridge CFTypeRef)(num));
   return numID == boolID;
}

上記の判断メソッドを使用し、元々がboolだったのかを判断します。
詳細はこちら