Обнаружить значение 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 в быстром закрытии