If you set a breakpoint immediately after calling getUser , the URLSession task completion handler, which runs asynchronously (that is, usually ends later if the request did not complete immediately or was not satisfied with any cached response), might not have been called .
If you place a breakpoint inside the dataTask completion dataTask , you should see your data at that point.
Personally, I would give getUser a completion handler so that you know when this will be done:
func getUser(completionHandler: @escaping (JSON?, Error?) -> Void) { let params = [ "email":"\(preferences.string(forKey: "preference_email")!)" ] let requestParams: [String: Any] = [ "action": "601", "params": params ] do { let requestObject = try JSONSerialization.data(withJSONObject: requestParams) var request = URLRequest(url: URL(string: "http://domain.tld/path/")!, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 20) request.httpBody = requestObject request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue("application/json", forHTTPHeaderField: "Accept") let task = URLSession.shared.dataTask(with: request) {data, response, error in guard let data = data, error == nil else { completionHandler(nil, error) return } completionHandler(JSON(data: data), nil) } task.resume() } catch { completionHandler(nil, error) } }
Then, when you call it, you can do something like:
getUser { json, error in guard let json = json else { print(error) return } // do something with json print(json) }
And just put your breakpoint in the getUser completion getUser . And remember that you have no assurances that the completion handler will be launched in the main queue or not, so you will need to send it to the dispatcher, as well as the UI, or simulate updates back to the main queue.