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;

emptyNumbernil に設定した後でこれを使用するとどうなりますか?

[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ありませnilNSNull。それで、それは任意の数を含んでいますか?

4

5 に答える 5

13

NSValueNSNumber、 ... は、値から作成され、常に 1 つを保持することになっています。特定の値のテストは、0使用している有効な値の範囲内にない場合にのみ機能します。

まれに、 「無効」または「未設定」を表す値があり、nil(標準コンテナなどで)使用できない場合に、NSNull代わりに使用できるコードの方が簡単な場合があります。

最初の例では、これは次のようになります。

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

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

ただし、区別する必要がない限りnil(つまり、コンテナー内にない場合)、「無効」と言う必要がない限り、その値を挿入 (または削除) できないことに注意してください。

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

2 番目の例については、が返され-intValueます0が、単にメッセージを送信するとnil返されるため0です。0たとえば、有効な値である前に設定されたNSNumberを取得することもできます。 すでに上で書いたように、 があなたにとって有効な値でない場合にのみ、このようなことを行うことができます。何が最適かは、要件によって完全に異なりますintValue0
0

要約してみましょう:

オプション1:

数値範囲のすべての値が必要ない場合は、1 つ (0または-1または ...) と-intValue/ ... を使用して、 「空」を具体的に表すことができます。これは明らかにあなたには当てはまりません。

オプション #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 に答える
0

NSNumbers は不変であり、何らかの数値を与えるファクトリ メソッドまたは初期メソッドでのみ作成できます。私の知る限り、0 を数えない限り、「空の」NSNumber になることはありません。

于 2010-09-15T10:15:27.980 に答える
0

辞書からオブジェクトを取得し、それが NSNumber になることを期待してから nil オブジェクトを返すことは非常に一般的です (少なくとも私にとっては)。これが発生して intValue を実行すると、クラッシュします。

私がしているのは、クラッシュよりもデフォルト値を取得したいので、nil 保護をセットアップすることです。

1 つの方法は次のとおりです。

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

そして、私はフロート用にそれと同じものを持っています。次に、少なくともデフォルト値を取得します。別の方法は、nil 保護のメソッドを作成することです。

-(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 に答える