19

如何检查 NSNumber 对象是 nil 还是空?

OK nil 很简单:

NSNumber *myNumber;
if (myNumber == nil)
    doSomething

但是,如果对象已经创建,但由于分配失败,其中没有值,我该如何检查呢?使用这样的东西?

if ([myNumber intValue]==0)
   doSomething

有没有一种通用的方法来测试对象的空性,比如 NSString 可用(见这篇文章)?

示例 1

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:@"" forKey:@"emptyValue"];
NSNumber *emptyNumber = [dict objectForKey:@"emptyValue"];

包含哪个值emptyNumber?如何检查是否emptyNumber为空?

示例 2

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:@"" forKey:@"emptyValue"];
NSString *myString = [dict objectForKey:@"emptyValue"];
if (myString == nil || [myString length] == 0)
    // got an empty value
    NSNumber *emptyNumber=nil;

如果我在emptyNumber设置为 nil 后使用它会发生什么?

[emptyNumber intValue]

我会得到零吗?

示例 3

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:@"" forKey:@"emptyValue"];
NSNumber *myEmptyValue = [dict objectForKey:@"emptyValue"];
if (myEmptyValue == nil)
    // NSLog is never called
    NSLog(@"It is empty!");

像这种方式 NSLog 永远不会被调用。myEmptyValue不是nil和不是NSNull。所以它包含一个任意数字?

4

5 回答 5

13

NSValue, NSNumber, ... 应该从一个值创建并始终持有一个。0仅当它不在您正在使用的有效值范围内时才能测试特定值。

在极少数情况下,如果您有一个表示“无效”“未设置”的值并且您不能使用nil(例如使用标准容器),那么您可以使用代码更直接地使用代码NSNull

在您的第一个示例中,这可能是:

[dict setValue:[NSNull null] forKey:@"emptyValue"];

if ([dict objectForKey:@"emptyValue"] == [NSNull null]) {
    // ...
}

但请注意,除非您需要区分nil(即不在容器中)并且说“无效” ,否则您不能简单地插入(或删除)该值:

if ([dict objectForKey:@"nonExistent"] == nil) {
    // ...
}

至于第二个例子-intValue给你0——但仅仅是因为发送消息nil返回00例如,您还可以获得之前设置为NSNumber的a ,这可能是一个有效值。正如我在上面已经写过的,如果对你来说不是一个有效的值, 你只能做这样的事情。请注意最有效的方法完全取决于您的要求。intValue0
0

让我试着总结一下

选项1:

如果您不需要数字范围内的所有值,则可以使用一个 ( 0or -1or ...) 和-intValue/ ... 来专门表示"empty"。这显然不是你的情况。

选项#2:

如果它们是“空”的,您根本不存储或删除容器中的值:

// add if not empty:
[dict setObject:someNumber forKey:someKey];    
// remove if empty:
[dict removeObjectForKey:someKey];
// retrieve number:
NSNumber *num = [dict objectForKey:someKey];
if (num == nil) {
    // ... wasn't in dictionary, which represents empty
} else {
    // ... not empty
}

然而,这意味着空密钥与从不存在或非法的密钥之间没有区别。

选项#3:

在极少数情况下,将所有键保留在字典中并用不同的值表示“空”会更方便。如果您不能使用数字范围中的一个,我们必须在其中放入不同的内容,因为NSNumber没有“空”的概念。Cocoa 已经NSNull为这种情况提供了:

// set to number if not empty:
[dict setObject:someNumber forKey:someKey];
// set to NSNull if empty:
[dict setObject:[NSNull null] forKey:someKey];
// retrieve number:
id obj = [dict objectForKey:someKey];
if (obj == [NSNumber null]) {
    // ... empty
} else { 
    // ... not empty
    NSNumber *num = obj;
    // ...
}

此选项现在允许您区分“空”“非空”“不在容器中”(例如非法密钥)。

于 2010-09-15T10:14:56.610 回答
3

NSNumber要么是nil,要么它包含一个数字,两者之间没有任何内容。“空性”是一个依赖于特定对象语义的概念,因此寻找一般的空性检查是没有意义的。

至于你的例子,有几件事发生:

NSMutableDictionary *hash = [NSMutableDictionary dictionary];
[hash setObject:@"" forKey:@"key"];
NSNumber *number = [hash objectForKey:@"key"];
NSLog(@"%i", [number intValue]);

将在这里NSLog打印,0但这只是因为intValue. NSString如果您将消息更改为只能NSNumber执行的操作,则代码将失败:

NSLog(@"%i", [number unsignedIntValue]);

这将抛出:

-[NSCFString unsignedIntValue]: unrecognized selector sent to instance 0x303c

这意味着您不会从哈希中获取一些一般的“空”值,而只是将NSString您存储在那里的值。

当您有一个空的 ( == nil)NSNumber并向其发送消息时,结果将为零。这只是一种简化代码的语言约定:

 (array != nil && [array count] == 0)
 (someNumber == nil ? 0 : [someNumber intValue])

会变成这样:

 ([array count] == 0)
 ([someNumber intValue])

希望这可以帮助。

于 2010-09-15T10:13:20.653 回答
1

处理 Swift 2.0 和 Parse:

var myNumber = yourArray!.objectForKey("yourColumnTitle")
    if (myNumber == nil) {
    myNumber = 0
      }

就我而言,我不得不:

    let myNumberIntValue = myNumber!.intValue
于 2015-12-08T21:41:53.030 回答
0

NSNumbers 是不可变的,只能使用工厂方法或初始方法创建,该方法为它们提供一些数值。据我所知,除非您数 0,否则不可能以“空”NSNumber 结尾。

于 2010-09-15T10:15:27.980 回答
0

从字典中取出一个对象是很常见的(至少对我来说),期望它是一个 NSNumber 然后让它返回一个 nil 对象。如果发生这种情况并且您执行 intValue 它将崩溃。

我所做的是设置 nil 保护,因为我宁愿获得默认值而不是崩溃。

一种方法是:

-(int) intForDictionary:(NSDictionary *)thisDict objectForKey: (NSString *)thisKey withDefault: (int)defaultValue
{
    NSNumber *thisNumber = [thisDict objectForKey:thisKey];
    if (thisNumber == nil) {
        return defaultValue;
    }
    return [thisNumber intValue];
}

我有一个就像它一样的花车。然后你至少得到你的默认值。另一种方法是创建一个用于零保护的方法..

-(NSNumber *)nilProtectionForNumber: (NSNumber *)thisNumber withDefault: (NSNumber *)defaultNumber
{
    if (thisNumber) {
        return thisNumber;
    }
    else
        return defaultNumber;
}

你会这样称呼的那个:

NSNumber *value = [self nilProtectionForNumber:[dict objectForKey:keyThatShouldBeNSNumber] withDefault:[NSNumber numberWithInt:0]];
于 2012-06-21T01:29:23.830 回答