0

I want to get the data from server api using Alamofire call. But after the api function executed, the data return is empty because Swift is asynchronous...

This code is call the server api:

func getAllModels(completion: @escaping (_ result: [String]?) -> ()) {
    var _modelList:[String] = []
    let url = BASE_URL + "getAllProductAndModelv2"
    Alamofire.request(url, method:.get, parameters: [:], encoding: JSONEncoding.default).responseJSON { response in

        switch response.result {
        case .success:
            if((response.result.value) != nil) {
                let data = NSData(contentsOf: URL(string: url)!)
                do {
                    if let data = data, let json = try JSONSerialization.jsonObject(with: data as Data) as? [String: Any], let models = json["models"] as? [[String:Any]] {
                        for model in models {
                            if let name = model["name"] as? String {
                                _modelList.append(name)
                            }
                        }
                    }
                }catch {
                    print("error")
                }
                completion(_modelList)
            }
        case .failure(let error):
            print(error)
            completion(nil)
        }
    }
}

And this code is get data from getAllModels function:

var models:[VirtualObject] = []

    RestApiManager().getAllModels(){ (result) -> () in
        print("************************************************")
        if let result = result {
            var array = result as Array
            for item in array {
                print(item)
                models.append(VirtualObject(url: URL(string: item)!)!)
            }
        }
        print("************************************************")
    }
    print(models)
    return models

I don't know how to use the callback function exactly to bind the data to return model.. Please help!

Duc Phan
  • 181
  • 5
  • 16
  • Does it print anything between those lines of `*`? – Milan Nosáľ Feb 28 '18 at 15:12
  • @MilanNosáľ yes it has data but the return line is empty – Duc Phan Feb 28 '18 at 16:01
  • that completion callback happens some time after the return call.. that is what asynchronous calls are about. the main execution thread does not wait until the data are back. what do you want to do with that model? instead of returning, you have to somehow use it in the callback (set it to some other property, etc.) – Milan Nosáľ Feb 28 '18 at 16:04
  • read more in: https://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-does-it-really-mean – Milan Nosáľ Feb 28 '18 at 16:08
  • but simply said, the callback that is in `{}` in `getAllModels()` will get executed later at some undefined point in time. the return will however happen right after calling `getAllModels` and `print`, which will be certainly before the callback gets executed – Milan Nosáľ Feb 28 '18 at 16:11
  • what i want now is how to bind the data to the return line but I don't know how to use callback function :( – Duc Phan Feb 28 '18 at 16:11
  • the thing is that with callback you cannot really do that - at least not without using semaphore, or similar mechanism, but that will kill the whole purpose of having async calls here.. unless there is a **very** good reason to do so, I would handle it using async callback.. can you add an example of how you would want to use the result of that return statement ? – Milan Nosáľ Feb 28 '18 at 16:15

1 Answers1

1

Use didSet observer of variables. And call api in viewDidload.

class ViewController: UIViewController {

var arrModals = [Any]() {
    didSet {
        print("this call when get all modals from server")
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    RestApiManager().getAllModels(){ (result) -> () in

        var arrTempModals = [Any]()

        if let result = result {
            var array = result as Array
            for item in array {
                print(item)
                arrTempModals.append(item)
            }
        }
        self.arrModals = arrTempModals
    }
} 

}

Hitesh Agarwal
  • 1,943
  • 17
  • 21