Detect a Null value in NSDictionary

I have an NSDictionary that’s populated from a JSON response from an API server. Sometimes the values for a key in this dictionary are Null

I am trying to take the given value and drop it into the detail text of a table cell for display.

  • UITableView infinite scrolling
  • Wifi position triangulation
  • Real time face detection is not working
  • What's wrong with using a category on NSObject to provide a default protocol implementation?
  • Core Data: NSPredicate for many-to-many relationship. (“to-many key not allowed here”)
  • iPad Multitasking support requires these orientations
  • The problem is that when I try to coerce the value into an NSString I get a crash, which I think is because I’m trying to coerce Null into a string.

    What’s the right way to do this?

    What I want to do is something like this:

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

    Here’s an example of the Dictionary:

    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";
    }
    

    If I just need to wrap all of this in a conditional, that’s fine. I just haven’t been able to figure out what that conditional is. Back in the Objective-C world I would compare against [NSNull null] but that doesn’t seem to be working in Swift.

    6 Solutions Collect From Internet About “Detect a Null value in NSDictionary”

    You can use the as? operator, which returns an optional value (nil if the downcast fails)

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

    I tested this example in a swift application

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

    and it correctly prints "Yay", whereas

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

    prints "hello!" as expected.

    You could also use is to check for the presence of a null:

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

    I’m using those combination. Additionaly that combination checks if object is not "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
    }
    

    It’s not that pretty as extension but work as charm 🙂

    NSNull is a class like any other. Thus you can use is or as to test an AnyObject reference against it.

    Thus, here in one of my apps I have an NSArray where every entry is either a Card or NSNull (because you can’t put nil in an NSArray). I fetch the NSArray as an Array and cycle through it, switching on which kind of object I get:

    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!
        }
    }
    

    That is not identical to your scenario, but it is from a working app converted to Swift, and illustrates the full general technique.

    my solution for now:

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

    tests look good so far…

    tests look good so far

    I had a very similar problem and solved it with casting to the correct type of the original NSDictionary value. If your service returns a mixed type JSON object like this

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

    you’ll have to fetch it’s values like that.

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

    This did solve my problem. See BAD_INSTRUCTION within swift closure