获取NSNumber的类型

时间:2010-03-25 19:34:45

标签: objective-c nsnumber

我想获得NSNumber实例的类型。

我在http://www.cocoadev.com/index.pl?NSNumber发现了这个:

 NSNumber *myNum = [[NSNumber alloc] initWithBool:TRUE];

 if ([[myNum className] isEqualToString:@"NSCFNumber"]) {
  // process NSNumber as integer
 } else if  ([[myNum className] isEqualToString:@"NSCFBoolean"]) {
  // process NSNumber as boolean
 }

好的,但这不起作用,编译器无法识别[myNum className]。 我正在为iPhone编译。

11 个答案:

答案 0 :(得分:76)

我建议使用-[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 Runtime Reference

答案 1 :(得分:43)

您可以通过这种方式获取类型,无需进行字符串比较:

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;

答案 2 :(得分:27)

如果您只想区分布尔值和其他任何东西,您可以利用布尔NSNumbers总是返回共享实例的事实:

NSNumber *num = ...;
if (num == (void*)kCFBooleanFalse || num == (void*)kCFBooleanTrue) {
   // num is boolean
} else {
   // num is not boolean
}

答案 3 :(得分:9)

NSNumber显然不保证返回的类型与用于创建它的方法匹配,所以这样做可能是一个坏主意。

但是,您可能会做这样的事情(您也可以与objc_getClass("NSCFNumber")等进行比较,但这可以说更便携了):

Class boolClass = [[NSNumber numberWithBool:YES] class];
/* ... */
if([myNum isKindOfClass:boolClass]) {
  /* ... */
}

答案 4 :(得分:4)

编译器警告你并且它不起作用的原因是因为-[NSObject className]在Mac OS X上的NSObject(在NSScriptClassDescription.h中)中的类别中声明并且未在iPhone上声明。 (显然,它不支持AppleScript。)NSStringFromClass([myNum class])是您应该在所有平台上安全使用的。可能性-className被声明为NSStringFromClass()周围的简单包装......

答案 5 :(得分:4)

使用方法-[NSNumber objCType] method获取类型。

如果类型等于@encode(BOOL),或者数字本身是kCFBooleanFalse或kCFBooleanTrue,那么它就是布尔值。

如果除了'以外还有别的什么,那就是一个数字。

如果它是',那么看起来唯一的支持方式,不检查私有类名,或者与未记录的单例进行比较,就是将一个元素组成一个元素,数字,然后使用NSJSONSerialization来获取字符串表示。最后,检查字符串表示是否包含字符串" true"或"假"。以下是检查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,那么这个方法可能不应该在紧密循环中使用。

答案 6 :(得分:3)

NSString *classString = NSStringFromClass([myNum class]);

那应该得到你想要的字符串。

答案 7 :(得分:0)

检查NSNumber是否包含bool值尝试:

if (strcmp([myNumber objCType], [@(YES) objCType]) == 0)
NSLog(@"%@", [myNumber boolValue] ? @"true" : @"false");

答案 8 :(得分:-1)

objCType文档说明The returned type does not necessarily match the method the number object was created with

其次,将数字类与给定类类型进行比较或假设布尔数实例为共享单例的其他方法不是记录的行为。

更多(不完全)可靠的方法是依赖于NSJSONSerialisation,因为它正确识别用bool创建的数字实例并在json中输出true / false。这是我们可以期待Apple在使用新SDK和不同架构时进行处理的事情。以下是代码:

+(BOOL) isBoolType:(NSNumber*) number {

    NSError* err;
    NSData* jsonData = [NSJSONSerialization dataWithJSONObject:@{@"key":number}
                                                       options:0
                                                         error:&err];

    NSString* jsonString = [[NSString alloc] 
                              initWithData:jsonData
                                  encoding:NSUTF8StringEncoding];

    return [jsonString containsString:@"true"]
            || [jsonString containsString:@"false"];

}

答案 9 :(得分:-1)

Swift版本

NSNumberclass-cluster,因此可以从实例中计算每种基础类型。此代码通过创建预期类型的​​实例,然后将其与未知类型进行比较,避免硬编码不同的NSNumber类型。

extension NSNumber {
    var isBool: Bool {
        return type(of: self) == type(of: NSNumber(booleanLiteral: true))
    }
}

答案 10 :(得分:-2)

检查对象是NSNumber类型:

if([obj isKindOfClass:NSClassFromString(@"__NSCFNumber")]) { //NSNumber }