NSNumberインスタンスのタイプを取得したい。
私は http://www.cocoadev.com/index.pl?NSNumber でこれを見つけました:
NSNumber * myNum = [[NSNumber alloc] initWithBool:TRUE]; if([[[myNum className] isEqualToString:@ "NSCFNumber"]){ // NSNumberを整数として処理します } else if([[myNum className] isEqualToString:@ "NSCFBoolean"]){ // NSNumberをブール値として処理します }
わかりましたが、これは機能しません。[myNum className]はコンパイラによって認識されません。 iPhone用にコンパイルしています。
-[NSNumber objCType]
メソッド。
それを行うことができます:
NSNumber * n = [NSNumber numberWithBool:YES];
if (strcmp([n objCType], @encode(BOOL)) == 0) {
NSLog(@"this is a bool");
} else if (strcmp([n objCType], @encode(int)) == 0) {
NSLog(@"this is an int");
}
タイプエンコーディングの詳細については、 Objective-Cランタイムリファレンス を参照してください。
この方法で型を取得できます。文字列の比較は必要ありません。
CFNumberType numberType = CFNumberGetType((CFNumberRef)someNSNumber);
numberTypeは次のいずれかになります。
enum CFNumberType {
kCFNumberSInt8Type = 1,
kCFNumberSInt16Type = 2,
kCFNumberSInt32Type = 3,
kCFNumberSInt64Type = 4,
kCFNumberFloat32Type = 5,
kCFNumberFloat64Type = 6,
kCFNumberCharType = 7,
kCFNumberShortType = 8,
kCFNumberIntType = 9,
kCFNumberLongType = 10,
kCFNumberLongLongType = 11,
kCFNumberFloatType = 12,
kCFNumberDoubleType = 13,
kCFNumberCFIndexType = 14,
kCFNumberNSIntegerType = 15,
kCFNumberCGFloatType = 16,
kCFNumberMaxType = 16
};
typedef enum CFNumberType CFNumberType;
ブール値と他のものを区別することだけが必要な場合は、ブール値のNSNumbersが常に共有インスタンスを返すという事実を利用できます。
NSNumber *num = ...;
if (num == (void*)kCFBooleanFalse || num == (void*)kCFBooleanTrue) {
// num is boolean
} else {
// num is not boolean
}
NSNumberは、返されたタイプがそれを作成するために使用されたメソッドと一致することを明示的に保証しないため、これを行うことはおそらく悪い考えです。
ただし、おそらく次のようなことを行うことができます(objc_getClass("NSCFNumber")
などと比較することもできますが、これはおそらくより移植性があります)。
Class boolClass = [[NSNumber numberWithBool:YES] class];
/* ... */
if([myNum isKindOfClass:boolClass]) {
/* ... */
}
メソッド-[NSNumber objCType] method
でタイプを取得します。
タイプが@encode(BOOL)と等しい場合、または数値自体がkCFBooleanFalseまたはkCFBooleanTrueである場合、それはブール値です。
「c」以外の場合は、数値です。
それが 'c'の場合、プライベートクラス名をチェックしたり、ドキュメント化されていないシングルトンと比較したりせずにサポートされている唯一の方法であると思われるのは、1つの要素と数値の配列を作成し、NSJSONSerializationを使用して文字列を取得することです。表現。最後に、文字列表現に文字列「true」または「false」が含まれているかどうかを確認します。 NSNumberがBOOLかどうかを確認するための完全なコードは次のとおりです。
-(BOOL)isBool
{
if(!strcmp(self.objCType, @encode(BOOL)) ||
self == (void*)kCFBooleanFalse ||
self == (void*)kCFBooleanTrue)
{
return YES;
}
if(strcmp(self.objCType, "c"))
{
return NO;
}
NSString * asString = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:@[self] options:kNilOptions error:nil] encoding:NSUTF8StringEncoding];
return [asString containsString:@"true"] || [asString containsString:@"false"];
}
NSJSONSerializationの使用は低速であり、@ NO/@ YESが常にkCFBooleanFalse/kCFBooleanTrueと等しくならない場合は、このメソッドをタイトループで使用しないでください。
Swiftの場合:
let numberType = CFNumberGetType(answer)
switch numberType {
case .charType:
//Bool
case .sInt8Type, .sInt16Type, .sInt32Type, .sInt64Type, .shortType, .intType, .longType, .longLongType, .cfIndexType, .nsIntegerType:
//Int
case .float32Type, .float64Type, .floatType, .doubleType, .cgFloatType:
//Double
}
コンパイラが警告を表示して機能しないのは、_-[NSObject className]
_がMac OS XのNSObjectのカテゴリ(NSScriptClassDescription.h内)で宣言されており、iPhoneでは宣言されていないためです。 (明らかにAppleScriptをサポートしていません。)NSStringFromClass([myNum class])
は、すべてのプラットフォームで安全に使用するために使用するものです。とにかく、_-className
_はNSStringFromClass()
の単純なラッパーとして宣言されています...
NSString *classString = NSStringFromClass([myNum class]);
必要な文字列が取得されます。
NSNumberにブール値が含まれていることを確認するにはこれを試してください:
if (strcmp([myNumber objCType], [@(YES) objCType]) == 0)
NSLog(@"%@", [myNumber boolValue] ? @"true" : @"false");