Подтвердить что ты не робот

Проверьте, нет ли NSNumber

Как проверить, является ли объект NSNumber нулевым или пустым?

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 никогда не вызывается. myEmptyValue не nil, а не NSNull. Таким образом, оно содержит произвольное число?

4b9b3361

Ответ 1

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 возвращает 0. Вы также можете получить 0, например. для NSNumber, для которого intValue было установлено значение 0 раньше, что может быть допустимым значением.
Как я уже писал выше, вы можете сделать только что-то подобное, если 0 не является допустимым значением для вас. Обратите внимание, что для вас, что работает лучше всего, зависит от ваших требований.

Позвольте мне попробовать суммировать:

Вариант №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;
    // ...
}

Теперь этот параметр позволяет различать "пустой" , "не пустой" и "не в контейнере" (например, незаконный ключ).

Ответ 2

NSNumber является либо nil, либо содержит число, между которыми нет ничего. "Пустота" - это понятие, которое зависит от семантики конкретного объекта, и поэтому нет смысла искать общую проверку пустоты.

Что касается ваших примеров, происходит несколько вещей:

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

NSLog будет печатать 0 здесь, но только потому, что метод a 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])

Надеюсь, что это поможет.

Ответ 3

NSNumber являются неизменяемыми и могут быть созданы только с помощью метода factory или исходного метода, который дает им некоторое числовое значение. Насколько я знаю, невозможно получить "пустой" NSNumber, если вы не подсчитаете 0.

Ответ 4

Очень часто (по крайней мере, для меня), чтобы получить объект из словаря, ожидайте, что он будет 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]];

Ответ 5

Работа с Swift 2.0 и Parse:

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

В моем случае мне тогда пришлось:

    let myNumberIntValue = myNumber!.intValue