-3

I update the user data (this is really simple I just parse a Json and save it to a global variable and in a coredata object) but the problem is that the statements that are after the function are executed before the function.

UpdateUserData()
print(User.user)

In the function above I call a public function that is in another file, but the print throws an empty dictionary and with a breakpoint I noticed that the print statement is executed before the function

UPDATE: this is the method for getting the data

public func UpdateUserData(){

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Usuarios")
request.returnsObjectsAsFaults = false
do {
    let result = try context.fetch(request)
    for dataCoreValue in result as! [NSManagedObject] {
        let urlString = "http://13.59.219.129/apostologo/api/v1/usuarios/\(dataCoreValue.value(forKey: "id") as! String)"
        print(urlString)
        let url = NSURL(string: urlString)!
        let urlSession = URLSession.shared
        let jsonQuery = urlSession.dataTask(with: url as URL, completionHandler: {
            data, response, error -> Void in
            if (error != nil) {
            }else{
                let jsonResult = (try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)) as! NSDictionary
                DispatchQueue.main.async {
                    Usuario.usuario = ["id":String(describing: (jsonResult["usuarios"] as! NSDictionary)["id_usuario"] as! NSNumber),
                                       "correo":(jsonResult["usuarios"] as! NSDictionary)["correo"] as! String,
                                       "fecha_nacimiento":(jsonResult["usuarios"] as! NSDictionary)["fecha_nacimiento"] as! String,
                                       "nombre":"\((jsonResult["usuarios"] as! NSDictionary)["nombres"] as! String) \((jsonResult["usuarios"] as! NSDictionary)["apellidos"] as! String)",
                        "tipo":(jsonResult["usuarios"] as! NSDictionary)["tipo"] as! String,
                        "token": Int((jsonResult["usuarios"] as! NSDictionary)["token"] as! String)!]
                    DispatchQueue.main.async {
                        dataCoreValue.setValue(Usuario.usuario["token"] as! Int, forKey: "tokens")
                        dataCoreValue.setValue(Usuario.usuario["token"] as! Int, forKey: "tokens")
                        dataCoreValue.setValue(Usuario.usuario["token"] as! Int, forKey: "tokens")
                        dataCoreValue.setValue(Usuario.usuario["token"] as! Int, forKey: "tokens")
                        dataCoreValue.setValue(Usuario.usuario["token"] as! Int, forKey: "tokens")
                        dataCoreValue.setValue(Usuario.usuario["token"] as! Int, forKey: "tokens")
                        do {
                            try context.save()
                            print("saved!")
                        } catch let error as NSError  {
                            print("Could not save \(error), \(error.userInfo)")
                        }
                    }
                }
            }
        })
        jsonQuery.resume()
    }
} catch {
    print("Failed")
}

}

  • I'm pretty sure `UpdateUserData` contains an network call with whose response you update your data. Mind sharing `UpdateUserData` method? – Rakesha Shastri Oct 03 '18 at 16:40
  • Done. @RakeshaShastri thanks for the help – Alfonso Mora De la Calle Oct 03 '18 at 16:43
  • You **are** performing a network call inside it. Network calls are asynchronous and take time and the response is handled in the background thread. So the execution continues with the statement after the method. So if you need to know the changes, you need to wait until you get the response in the completion of the network call and then print in the completion. Alternatively, you could add a completion to `UpdateUserData` and call that inside the network completion. – Rakesha Shastri Oct 03 '18 at 16:47
  • This comes up ALL THE TIME. You need to refactor your `UpdateUserData()` function to take a completion handler. See the link to the duplicate question for several different examples, including one in Swift 4 syntax. – Duncan C Oct 03 '18 at 17:01

1 Answers1

0

UpdateUserData() is asynchronous, because it is making a network request, and that's why the print statement is executed, in the main thread, before updating the user data.

You could try this in a playground:

DispatchQueue.main.async {
    print("Hello")
}
print("world!")

prints

world!
Hello

You could use Dispatch groups if you'd like to enforce the order of execution:

let group = DispatchGroup()
group.enter()

DispatchQueue.main.async {
    print("Hello")
    group.leave()
}

group.notify(queue: .main) {
    print("world!")
}

//Hello    
//world!
ielyamani
  • 17,807
  • 10
  • 55
  • 90