Reputation: 514
I am parsing a feed of json data representing events. On a day where there ARE events, the json feed will be a Dictionary of Dictionaries, and looks something like this:
{
"19374176" :
{
"event_title" : "Cool Fun Thing to Do",
"event_description" : "Have fun and do something cool",
"event_start_time" : "13:00:00",
"event_end_time" : "14:00:00"
},
"90485761634" :
{
"event_title" : "Nap Time",
"event_description" : "Lay down and go to sleep.",
"event_start_time" : "15:00:00",
"event_end_time" : "16:00:00"
}
}
I have a structure set up and I can decode and use this information the way I would like to currently with this code that is part of a larger function:
URLSession.shared.dataTask(with: url){(data, response, error) in
if error != nil {
print("session error: ", error!.localizedDescription)
}
guard let data = data else { return }
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
print(data)
var eventData = try decoder.decode([String:Event].self, from: data)
DispatchQueue.main.async{
self.events = Array(eventData.values).sorted(by: {$0.timeStart < $1.timeStart
})
self.updateView()
self.refreshControl.endRefreshing()
self.activityIndicatorView.stopAnimating()
}
} catch DecodingError.typeMismatch(let type, let context){
//No Dictionary of Events in Data
print("key:", type, "context: ", context)
} catch let jsonError{
print("json error: ", jsonError)
}
}.resume()
}
My issue right now is that, on days where there no events, the json feed is an empty Array:
[]
This causes a type mismatch which I handle, but if I try to call the updateView, refreshControl, or activityIndicatorView's functions from the catch, I get an error that I cannot call them outside the main thread.
I tried to do nested try blocks to assign the eventData variable (first to see if it is an [String] ((empty array, no events)) and then to [String:Any] ((array with values of events))), but that gave me an error for the URLSession.
Is there a better approach to this to see if the json is an empty array vs a populated dictionary of my Event values and update the views regardless?
Upvotes: 1
Views: 70
Reputation: 100503
Try refreshing them outside of any blocks
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
print(data)
var eventData = try decoder.decode([String:Event].self, from: data)
self.events = Array(eventData.values).sorted(by: {$0.timeStart < $1.timeStart
} catch DecodingError.typeMismatch(let type, let context){
//No Dictionary of Events in Data
print("key:", type, "context: ", context)
} catch let jsonError{
print("json error: ", jsonError)
}
DispatchQueue.main.async{
self.updateView()
self.refreshControl.endRefreshing()
self.activityIndicatorView.stopAnimating()
}
Upvotes: 3