13

I'm reading json from a URL and, again (I had the same issue with ObjectiveC) the values crash my app. I don't have any problems with Strings and Numbers. I can println(value) but when I assign the value into a UILabel, it crashes.

I use this method to read the JSON:

func jsonFromURL(jsonURL: String) -> Dictionary<String, AnyObject> {
    var jsonNSURL: NSURL = NSURL(string: jsonURL)
    let jsonSource: NSData = NSData(contentsOfURL: jsonNSURL)
    var json = NSJSONSerialization.JSONObjectWithData(jsonSource, options:NSJSONReadingOptions.MutableContainers, error: nil) as Dictionary<String, AnyObject>
    return json
}

...and this code to assign values into a UILabel inside a custom Cell

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell? {

    var regularTextCell:celda = celda(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
    var cell:celda = NSBundle.mainBundle().loadNibNamed("celda", owner: self, options: nil)[0] as celda

    cell.name.text = myJson["list"]![indexPath.row]!["name"] as String
    cell.id.text = "id: " + String(myJson["list"]![indexPath.row]!["id"] as Int)

    // THIS line crash because some values of adress are <null>
    cell.address.text = myJson["list"]![indexPath.row]!["address"] as String

    return cell

}

You can view an example of the JSON at: https://dl.dropboxusercontent.com/u/787784/example.json

Thanks!

neminem
  • 2,658
  • 5
  • 27
  • 36
Francis Vega
  • 152
  • 1
  • 2
  • 10
  • possible duplicate of [Detect a Null value in NSDictionary](http://stackoverflow.com/questions/24026609/detect-a-null-value-in-nsdictionary) – Jeff Jun 09 '14 at 22:15

4 Answers4

17

You'll get an exception from syntax like object as String if object is not a String. You can avoid the exception by using object as? String which may result in a nil being assigned into your text.

In your specific case you could use:

cell.address.text = (myJson["list"]![indexPath.row]!["address"] as? String) ?? "default"

where I've replaced your as with as? and exploited the nil-coalescing operator ??.

GoZoner
  • 67,920
  • 20
  • 95
  • 145
9

I found this solution in online Swift tutorial. It's very nice solution how to deal with null value in Swift.

This is the concept:

 let finalVariable = possiblyNilVariable ?? "Definitely Not Nil Variable"

In tutorial example :

  let thumbnailURL = result["artworkUrl60"] as? String ?? ""

Here is the link for tutorial: http://jamesonquave.com/blog/developing-ios-8-apps-using-swift-interaction-with-multiple-views/

Marijan V.
  • 403
  • 5
  • 6
  • I tried to do this but i wanted to unwrap the values by doing let thumbnailURL = (result["artworkUrl60"] as? String ?? "")! but didn't work is there a good way that while the assignment can i unwrap it? @Marijan V. – Cesar Mtz Aug 16 '16 at 03:29
6

You can change the offending line to:

if let address = myJson["list"]![indexPath.row]!["address"] as? String {
  cell.address.text = address
}
else {
  cell.address.text = ""
}

The as? operator will cast the value the same way as would, but if the casting fails, it will instead assign nil

The if let … syntax combines this with a check and when the casting fails (and nil is returned) the else block runs instead

Jiaaro
  • 74,485
  • 42
  • 169
  • 190
1

If you use:

You'll be able to go like this:

let yourJSON = JSON.fromURL("https://dl.dropboxusercontent.com/u/787784/example.json")
for (i, node) in yourJSON["list"] {
    let isnull = node["address"].isNull
    println("//[\"list\"][\(i)]:\t\(isnull)")
}

//["list"][0]:  false
//["list"][1]:  false
//["list"][2]:  true
//["list"][3]:  false
//["list"][4]:  false
//["list"][5]:  true
//["list"][6]:  false
//["list"][7]:  false
//["list"][8]:  false
//["list"][9]:  false
//["list"][10]: false
//["list"][11]: false
//["list"][12]: true
//["list"][13]: false
//["list"][14]: false
//["list"][15]: false
//["list"][16]: false
//["list"][17]: false
//["list"][18]: false
//["list"][19]: false

No ? or ! required and it does not crash on nonexistent nodes.

dankogai
  • 1,627
  • 12
  • 7