Gosdi Gosdi - 16 days ago 8
iOS Question

iOs PickerView empty after read Json

I'm making an app in iOs and everything is going fairly well but for one bug that I can't fix.
When the user starts the app for the first time the app request a Json from my server. When the json is read, I show the result in a picker view.
The problem es that the pickerview always shows empty until the user touchs the screen. I've tried quite a few things but nothing works. In thoery is empty because the json hasn't been read, but this is not the case because in the console I can see that the json is ready.
Could anybody give me a clue, please? here you are some pieces of code:

override func viewDidLoad() {

super.viewDidLoad()
readJson()
warning.isHidden = true
self.codeInput.delegate = self;

let when = DispatchTime.now() + 0.2 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) {
// Your code with delay
self.showLoader()
}

picker.reloadAllComponents()
}


And the part where I read the json

func readJson(){
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(url: requestURL)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest as URLRequest, completionHandler: {
(data, response, error) -> Void in

let httpResponse = response as! HTTPURLResponse
let statusCode = httpResponse.statusCode


if (statusCode == 200) {
print("Everyone is fine, file downloaded successfully.")
do{

let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]

if let events = json["events"] as? [[String: AnyObject]] {

for event in events {

//here I read the json and I save the data in my custom array
}
self.picker.reloadAllComponents()
}
print(self.eventsArray)
}

}catch {
print("Error with Json: \(error)")
}
}
else{
print(statusCode)
}
})
picker.reloadAllComponents()
task.resume()
}

Answer

You need to do a couple of things:

You need to move the call to reload the picker view to inside the completion handler for your data task. That closure gets called once the data has been loaded.

However, the completion methods of URLSession tasks get executed on a background thread. Thus you'll need to wrap your call in a GCD call to the main thread. Add this code as the very last line in your completion closure, right before the closing brace:

DispatchQueue.main.async{
    picker.reloadAllComponents()
}     

(That's Swift 3 syntax.)

Comments