获取 NSNumber 的类型

发布于 2024-08-26 13:05:22 字数 488 浏览 11 评论 0原文

我想获取 NSNumber 实例的类型。

我发现 http://www.cocoadev.com/index.pl?NSNumber this:

 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 进行编译。

I want to get the type of NSNumber instance.

I found out on http://www.cocoadev.com/index.pl?NSNumber this:

 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
 }

Ok, but this doesn't work, the [myNum className] isn't recognized by the compiler.
I'm compiling for iPhone.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

帅气尐潴 2024-09-02 13:05:22

我建议使用 -[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 运行时参考

I recommend using the -[NSNumber objCType] method.

It allows you to do:

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");
}

For more information on type encodings, check out the Objective-C Runtime Reference.

心意如水 2024-09-02 13:05:22

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

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;

You can get the type this way, no string comparisons needed:

CFNumberType numberType = CFNumberGetType((CFNumberRef)someNSNumber);

numberType will then be one of:

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;
忘年祭陌 2024-09-02 13:05:22

如果您想要区分布尔值和其他任何值,您可以利用布尔 NSNumbers 始终返回共享实例的事实:

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

If all you want is to differentiate between booleans and anything else, you can make use of the fact that boolean NSNumbers always return a shared instance:

NSNumber *num = ...;
if (num == (void*)kCFBooleanFalse || num == (void*)kCFBooleanTrue) {
   // num is boolean
} else {
   // num is not boolean
}
陪你搞怪i 2024-09-02 13:05:22

NSNumber 明确不保证返回的类型与用于创建它的方法相匹配,因此这样做可能是一个坏主意。

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

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

NSNumber explicitly doesn't guarantee that the returned type will match the method used to create it, so doing this at all is probably a bad idea.

However, you could probably do something like this (you could also compare to objc_getClass("NSCFNumber") etc., but this is arguably more portable):

Class boolClass = [[NSNumber numberWithBool:YES] class];
/* ... */
if([myNum isKindOfClass:boolClass]) {
  /* ... */
}
断爱 2024-09-02 13:05:22

在斯威夫特中:

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
}

In 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
}
烟酉 2024-09-02 13:05:22

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

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

如果不是“c”,那么它就是一个数字。

如果它是“c”,那么似乎是唯一受支持的方法,无需检查私有类名或与未记录的单例进行比较,而是创建一个包含一个元素(数字)的数组,然后使用 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,那么此方法可能不应该在紧密循环中使用。

Use the method -[NSNumber objCType] method to get the type.

If the type's equal to @encode(BOOL), or the number itself is kCFBooleanFalse, or kCFBooleanTrue, it's a boolean.

If it's anything else but 'c', it's a number.

If it's 'c', what appears to be the only way supported way, without checking against private class names, or comparing against undocumented singletons, is to turn make an array of one element, the number, and then use NSJSONSerialization to get the string representation. Finally, check if the string representation contains the string "true" or "false". Here is the full code for checking if an NSNumber is a 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"];
}

Note that using NSJSONSerialization is slow and if @NO/@YES ever stops always equalling kCFBooleanFalse/kCFBooleanTrue, then this method probably shouldn't be used in a tight loop.

她如夕阳 2024-09-02 13:05:22

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

The reason the compiler warns you and it doesn't work is because -[NSObject className] is declared in a category on NSObject on Mac OS X (in NSScriptClassDescription.h) and not declared on iPhone. (It doesn't support AppleScript, obviously.) NSStringFromClass([myNum class]) is what you should use to be safe across all platforms. Odds are that -className is declared as a simple wrapper around NSStringFromClass() anyway...

年少掌心 2024-09-02 13:05:22
NSString *classString = NSStringFromClass([myNum class]);

这应该是你想要的字符串。

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

That should ger the string you want.

嘴硬脾气大 2024-09-02 13:05:22

要检查 NSNumber 是否包含 bool 值,请尝试以下操作:

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

To check that NSNumber contains a bool value Try this:

if (strcmp([myNumber objCType], [@(YES) objCType]) == 0)
NSLog(@"%@", [myNumber boolValue] ? @"true" : @"false");
愿与i 2024-09-02 13:05:22

objCType 文档指出返回的类型不一定与创建数字对象的方法匹配

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

一种更(但不完全)可靠的方法是依赖 NSJSONSerialization,因为它可以正确识别使用 bool 创建的数字实例并在 json 中输出 true/false。我们可以期望苹果在使用新的 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"];

}

objCType documentation states that The returned type does not necessarily match the method the number object was created with

Secondly, other methods of comparing the class of number to a given class type or assuming boolean number instances to be shared singletons are not documented behaviour.

A more(not completely though) reliable way is to depend on NSJSONSerialisation as it correctly recognises number instances created with bool and outputs true/false in json. This is something we can expect Apple to take care of while moving with new SDKs and on different architectures. Below is the code:

+(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"];

}
江湖正好 2024-09-02 13:05:22

Swift 版本

NSNumber类簇 因此每个底层类型都可以从实例中计算出来。此代码通过创建预期类型的​​实例,然后将其与未知类型进行比较,避免了对不同 NSNumber 类型进行硬编码。

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

Swift Version

NSNumber is a class-cluster so each underlying type can be figured from the instance. This code avoids hard-coding the different NSNumber types by creating an instance of the expected type, and then comparing it against the unknown type.

extension NSNumber {
    var isBool: Bool {
        return type(of: self) == type(of: NSNumber(booleanLiteral: true))
    }
}
青柠芒果 2024-09-02 13:05:22

检查对象是否为 NSNumber 类型:

if([obj isKindOfClass:NSClassFromString(@"__NSCFNumber")])
{
//NS编号
}

check object is of NSNumber type :

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文