Обнаружить значение Null в NSDictionary

У меня есть NSDictionary, который заполняется из ответа JSON с сервера API. Иногда значения для ключа в этом словаре Null

Я пытаюсь принять заданное значение и отбросить его в текст детализированной ячейки таблицы для отображения.

Проблема в том, что, когда я пытаюсь заставить значение в NSString, я получаю сбой, который, я думаю, связан с тем, что я пытаюсь принудить Null к строке.

Каков правильный способ сделать это?

Я хочу сделать что-то вроде этого:

cell.detailTextLabel.text = sensor.objectForKey( "latestValue" ) as NSString

Вот пример словаря:

Printing description of sensor:
{
    "created_at" = "2012-10-10T22:19:50.501-07:00";
    desc = "<null>";
    id = 2;
    "latest_value" = "<null>";
    name = "AC Vent Temp";
    "sensor_type" = temp;
    slug = "ac-vent-temp";
    "updated_at" = "2013-11-17T15:34:27.495-07:00";
}

Если мне просто нужно обернуть все это условным, это прекрасно. Я просто не мог понять, что это за условное. Вернемся в мир Objective-C, который я бы сравнил с [NSNull null], но, похоже, он не работает в Swift.

Ответ 1

Вы можете использовать оператор as?, который возвращает необязательное значение (nil, если сбой сбрасывается)

if let latestValue = sensor["latestValue"] as? String {
    cell.detailTextLabel.text = latestValue
}

Я тестировал этот пример в быстром приложении

let x: AnyObject = NSNull()
if let y = x as? String {
    println("I should never be printed: \(y)")
} else {
    println("Yay")
}

и он правильно печатает "Yay", тогда как

let x: AnyObject = "hello!"
if let y = x as? String {
    println(y)
} else {
    println("I should never be printed")
}

выводит "hello!", как ожидалось.

Ответ 2

Вы также можете использовать is для проверки наличия нулевого значения:

if sensor["latestValue"] is NSNull {
    // do something with null JSON value here
}

Ответ 3

Я использую эту комбинацию. Кроме того, эта комбинация проверяет, не является ли объект "null".

func isNotNull(object:AnyObject?) -> Bool {
    guard let object = object else {
        return false
    }
    return (isNotNSNull(object) && isNotStringNull(object))
}

func isNotNSNull(object:AnyObject) -> Bool {
    return object.classForCoder != NSNull.classForCoder()
}

func isNotStringNull(object:AnyObject) -> Bool {
    if let object = object as? String where object.uppercaseString == "NULL" {
        return false
    }
    return true
}

Это не так красиво, как расширение, но работает как прелесть:)

Ответ 4

NSNull - это класс, как любой другой. Таким образом, вы можете использовать is или as для проверки ссылки AnyObject на него.

Таким образом, здесь, в одном из моих приложений, у меня есть NSArray, где каждая запись является либо Картой, либо NSNull (потому что вы не можете поместить nil в NSArray). Я получаю NSArray как массив и цикл через него, включающий какой тип объекта я получаю:

for card:AnyObject in arr {
    switch card { // how to test for different possible types
    case let card as NSNull:
        // do one thing
    case let card as Card:
        // do a different thing
    default:
        fatalError("unexpected object in card array") // should never happen!
    }
}

Это не идентично вашему сценарию, но это из рабочего приложения, преобразованного в Swift, и иллюстрирует полную общую технику.

Ответ 5

мое решение:

func isNull(someObject: AnyObject?) -> Bool {
    guard let someObject = someObject else {
        return true
    }

    return (someObject is NSNull)
}

тесты хорошо выглядят...

тесты пока выглядят хорошо

Ответ 6

У меня была очень похожая проблема и она была решена с литьем к правильному типу исходного значения NSDictionary. Если ваша служба возвращает объект JSON смешанного типа, подобный этому

{"id":2, "name":"AC Vent Temp", ...}

вам нужно будет получить такие значения.

var id:int = sensor.valueForKey("id") as Int;
var name:String? = sensor.valueForKey("name") as String;

Это решило мою проблему. См. BAD_INSTRUCTION в быстром закрытии