The problem is when there is incomplete data NSJSONSerialization.JSONObjectWithData
is crashing the application giving unexpectedly found nil while unwrappin
The problem is that you cast the result of the JSON deserialization before checking for an error. If the JSON data is invalid (e.g. incomplete) then
NSJSONSerialization.JSONObjectWithData(...)
returns nil
and
NSJSONSerialization.JSONObjectWithData(...) as NSDictionary
will crash.
Here is a version that checks for the error conditions correctly:
var error:NSError? = nil
if let jsonObject: AnyObject = NSJSONSerialization.JSONObjectWithData(receivedData, options: nil, error:&error) {
if let dict = jsonObject as? NSDictionary {
println(dict)
} else {
println("not a dictionary")
}
} else {
println("Could not parse JSON: \(error!)")
}
Remarks:
The JSON reading option .AllowFragments
does not help here. Setting this option
only allows that top-level objects that are not an instance of NSArray
or NSDictionary
, for example
{ "someString" }
You can also do it in one line, with an optional cast as?
:
if let dict = NSJSONSerialization.JSONObjectWithData(receivedData, options: nil, error:nil) as? NSDictionary {
println(dict)
} else {
println("Could not read JSON dictionary")
}
The disadvantage is that in the else
case you cannot distinguish whether reading
the JSON data failed or if the JSON did not represent a dictionary.
For an update to Swift 3, see LightningStryk's answer.