web-dev-qa-db-ja.com

NSNumberが空かどうかを確認します

NSNumberオブジェクトがnilまたは空かどうかを確認するにはどうすればよいですか?

OK nilは簡単です:

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

しかし、オブジェクトが作成されたが、割り当てが失敗したためにオブジェクトに値がない場合、これを確認するにはどうすればよいですか?このようなものを使用しますか?

if ([myNumber intValue]==0)
   doSomething

利用可能なNSStringのように空でオブジェクトをテストするための一般的な方法はありますか(これを参照してください post )?

例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が呼び出されることはありません。 myEmptyValuenilではなく、NSNullでもありません。それで、それは任意の数を含みますか?

18
testing

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

"invalid"または"not set"を表す値があり、nilを使用できない場合、コードの操作がより簡単になるまれなケースです。 (たとえば、標準コンテナの場合)代わりに NSNull を使用できます。

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

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

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

ただし、nilを区別する必要がない限り(つまり、コンテナ内にない場合)、その値を挿入(または削除)することはできません。たとえば、"invalid"

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

2番目の例については、-intValue0を返しますが、単にnilにメッセージを送信すると0が返されるためです。 。 0を取得することもできます。以前にNSNumber0に設定されていたintValueの場合、これは有効な値である可能性があります。
すでに上で書いたように、0あなたにとって有効な値ではないの場合にのみ、このようなことを行うことができます。 for yoに注意してください。何が最も効果的かは、要件によって異なります。

要約を試してみましょう:

オプション#1:

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

オプション#2:

"empty":の場合、値をコンテナに保存したり、コンテナから削除したりしないでください。

// 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:

まれに、すべてのキーを辞書に保持し、"empty"を異なる値で表す方が便利な場合があります。 NSNumberには"empty"の概念がないため、番号範囲の1つを使用できない場合は、別の方法で入力する必要があります。 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;
    // ...
}

このオプションにより、"empty""not empty""not in the container"(例:不正なキー)を区別できるようになりました。

12
Georg Fritzsche

NSNumbernilであるか、数字が含まれていて、間に何もありません。 「空」は特定のオブジェクトのセマンティクスに依存する概念であるため、一般的な空のチェックを探すことは意味がありません。

あなたの例に関しては、いくつかのことが起こっています:

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

NSLogはここに0を出力しますが、これはintValueNSStringメソッドがあるためです。メッセージをNSNumberのみが実行できるものに変更すると、コードは失敗します。

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

これはスローします:

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

つまり、notハッシュから一般的な「空の」値を取得し、そこに保存したNSStringを取得するだけです。

空の(== nilNSNumberがあり、それにメッセージを送信すると、結果はゼロになります。これは、コードを単純化する単なる言語規則です。

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

これに変わります:

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

お役に立てれば。

3
zoul

Swift 2.0および解析:

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

私の場合、次のことを行う必要がありました。

    let myNumberIntValue = myNumber!.intValue
0
B. Wolf

辞書からオブジェクトを取得し、それが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];
}

そして、私はフロート用にそれと同じようなものを持っています。次に、少なくともデフォルト値を取得します。もう1つの方法は、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]];
0
badweasel

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

0
zem