-1

I need some help with my school project.
Why is print(segueShouldOccur) printed before doAPI(). When I actually call doApi() before the print(seagueShouldOccur). I'm talking about the method: shouldPerformSegue. The Rest Api does work (already tested).

class ViewController: UIViewController {
    var loginArr = [String]()
    @IBOutlet weak var _output: UILabel!

    @IBOutlet weak var _username: UITextField!

    @IBOutlet weak var _password: UITextField!

    @IBAction func doLogin(_ sender: Any) {
        loginArr.removeAll()
        let username = _username.text;
        let password = _password.text;
        loginArr.append(username!);
        loginArr.append(password!);
        self._output.text = username;
    }

    func doApi() -> Bool{
        let headers = [
            "cache-control": "no-cache",
            "postman-token": "6f8a-12c6-87a1-ac0f25d6385a"
        ]
        let url = "https://projects2018.sz-ybbs.ac.at/~szmed/indyapp/indyapi.php?func=0&user=" + _username.text! + "&pass=" + _password.text!

        let request = NSMutableURLRequest(url: NSURL(string: url)! as URL,
            cachePolicy: .useProtocolCachePolicy,
            timeoutInterval: 10.0)

        var check = false;

        request.httpMethod = "GET"
        request.allHTTPHeaderFields = headers

        let session = URLSession.shared
        let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
            if error == nil && data != nil {
                do {
                    let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:AnyObject]
                   //do your stuff
                    print(json);
                    check = true;

                } catch {
                }
            }
            else if error != nil
            {
            }
        }).resume()
        return check;
        }

     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
           let DashboardC = segue.destination as! DashboardController
            DashboardC.receivedStringArr = loginArr
           }

    override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
        if identifier == "performSegueLogin" { // you define it in the storyboard (click on the segue, then Attributes' inspector > Identifier
            var segueShouldOccur = doApi()
            if (!segueShouldOccur){
                print("1 - false");
                print(segueShouldOccur);
                return false;
            }else{
                print("2 - true");
                print(segueShouldOccur);
                return true;
            }
        }
        return false;
    } 
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Pheeerox
  • 3
  • 1
  • Does this answer your question? [is session.dataTask asynchronous in swift?](https://stackoverflow.com/questions/46954162/is-session-datatask-asynchronous-in-swift) – mag_zbc Dec 09 '19 at 12:44
  • ok, so now i know its async. But how do i handle such code. I assume to implement any kind of Listener? – Pheeerox Dec 09 '19 at 12:46
  • What exactly do you mean by _handle such code_? Handle how? What do you want to do? – mag_zbc Dec 09 '19 at 12:48
  • you should use a completion handler that will check if the task has been completed. – Keshu R. Dec 09 '19 at 12:50
  • this should be an login: i want to proof if the login data is correct. and if it's correct i want to swap to another storyboard (equals Activity in Android). – Pheeerox Dec 09 '19 at 12:55

1 Answers1

0

session.dataTask is asynchronous. If you want to know when your api call has completed, you can use completion handler like this :

func doApi(completion : @escaping (Bool?,Error?) -> ()) {
let headers = [
"cache-control": "no-cache",
"postman-token": "6f8a-12c6-87a1-ac0f25d6385a"
]
let url = "https://projects2018.sz-ybbs.ac.at/~szmed/indyapp/indyapi.php?func=0&user=" + _username.text! + "&pass=" + _password.text!

 let request = NSMutableURLRequest(url: NSURL(string: url)! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)

var check = false;

request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
    if error == nil && data != nil {
        do {
            let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:AnyObject]
           //do your stuff
            print(json);
            check = true;
        } catch {
        }
        completion(true,nil)

    }
    else if error != nil
    {
        completion(false,error)
    }
}).resume()
return check;
}

then you can call your function like this :

doApi { (isSuccess, errorMessage) in
if isSuccess {
    // perform your operations
} else {
    print(errorMessage?.localizedDescription ?? "Some error occured")
}
}
Keshu R.
  • 5,045
  • 1
  • 18
  • 38
  • glad to help :) – Keshu R. Dec 09 '19 at 14:50
  • but there is one more problem i just saw, if isSucess is true i want to execute following code 'code' let loginController = UIStoryboard(name: "Main", bundle: nil) let dashboardController = loginController.instantiateViewController(withIdentifier: "DashboardController") as! DashboardController //dashboardController.receivedStringArr = loginArr; self.navigationController?.pushViewController(dashboardController, animated: true) 'code' but it says i cant do it in async call. any suggestions? – Pheeerox Dec 09 '19 at 14:54
  • just paste it in isSuccess block ... replace my comment (// perform your operations) with your code.... – Keshu R. Dec 09 '19 at 14:56