Egle Matutyte
Egle Matutyte

Reputation: 225

Swift function execute after another function done

Hi I got problem I am trying to call function after another function is fully completed, I tried to do that using closures, but still it's not helping and app present new controller and after that I get response from function which performing login by making request to server. How to fix it?

   performLogin(userName: UserDefaults.standard.value(forKey: "saved_username")! as! String, password: UserDefaults.standard.value(forKey: "saved_password")! as! String){ () -> () in
            self.finishLoggingIn()
        }

Function which making request to server:

 public func performLogin(userName: String, password: String, complete: ()->()){

    let duom = LoginModel()
    duom.JsonResult(param1: userName, param2: password, param3: self){ () -> () in
}}

Function which open another Controller:

 func finishLoggingIn() {
    print("Finish logging in")


    let appDelegate = UIApplication.shared.delegate! as! AppDelegate

    let initialViewController = self.storyboard!.instantiateViewController(withIdentifier: "MainVC")
    appDelegate.window?.rootViewController = initialViewController
    appDelegate.window?.makeKeyAndVisible()

    UserDefaults.standard.setValue(true, forKey: "isLoggedIn")
    UserDefaults.standard.synchronize()
    dismiss(animated: true, completion: nil)
}

Json result function:

internal func JsonResult (param1: String, param2: String, param3: UIViewController, complete:@escaping ()->()){

Json().login(userName: param1, password: param2) { (json, error) in


    if error != nil {
        //Show alert
        print(error!.localizedDescription)
        DispatchQueue.main.async {
            AlertController.showErrorWith(title: "Error", message: error!.localizedDescription, controller: param3) {

            } 
        }


    }

    //Access JSON here

    if let jsonDic = json as? JSON {

        if (jsonDic["result"].exists()){
                 print(jsonDic["result"]["ubus_rpc_session"].stringValue)
              if (jsonDic["result"].arrayValue.contains(6)) {
                 self.loginToken = "[6]"
              } else {
                 for item in jsonDic["result"].arrayValue {
                 self.loginToken = item["ubus_rpc_session"].stringValue
                               }
              }
        }
         if (jsonDic["error"].exists()){

                self.loginToken = jsonDic["error"]["message"].stringValue

                }
    }
    print(self.loginToken)

  if (!self.loginToken.isEmpty) {

     if ((!self.loginToken.contains("[6]")) && (!self.loginToken.contains("Failed"))) {

        UserDefaults.standard.setValue(self.loginToken, forKey: "saved_token")
               print(self.loginToken)



    }else {
        if (self.loginToken.contains("Access denied")) {
            self.loginToken = "Access denied"
            print(self.loginToken)
        } else if (self.loginToken.contains("Failed")) {
            self.loginToken = "Connection timeout"
        } else if (self.loginToken.contains("[6]")) {
            DispatchQueue.main.async {
                AlertController.showErrorWith(title: "Error", message: "Wrong username or password", controller: param3) {

                }
            }
            self.loginToken = "Login Error"
            print(self.loginToken)
        }


    }
    }
    self.loginToken = ""
}
   complete()


}

Upvotes: 1

Views: 2555

Answers (2)

shallowThought
shallowThought

Reputation: 19602

1st:

You are never calling the completion handler of performLogin:

public func performLogin(userName: String, password: String, complete: ()->()){

    let duom = LoginModel()
    duom.JsonResult(param1: userName, param2: password, param3: self){ () -> () in
        complete() // this line was missing  
    }
}

2nd:

In the JsonResult method (please start method names lower case!) you are calling the completion closure outside Json().logins completion closure. As a result JsonResults completion closure is called before Json().login has finished.

To fix this, call JsonResults completion closure from within Json().logins completion closure:

internal func JsonResult (param1: String, param2: String, param3: UIViewController, complete:@escaping ()->()){

    Json().login(userName: param1, password: param2) { (json, error) in
        if error != nil {
            //Show alert
            print(error!.localizedDescription)
            DispatchQueue.main.async {
                AlertController.showErrorWith(title: "Error", message: error!.localizedDescription, controller: param3) {

                }
            }
        }

        //Access JSON here

        if let jsonDic = json as? JSON {
            if (jsonDic["result"].exists()){
                print(jsonDic["result"]["ubus_rpc_session"].stringValue)
                if (jsonDic["result"].arrayValue.contains(6)) {
                    self.loginToken = "[6]"
                } else {
                    for item in jsonDic["result"].arrayValue {
                        self.loginToken = item["ubus_rpc_session"].stringValue
                    }
                }
            }
            if (jsonDic["error"].exists()){        
                self.loginToken = jsonDic["error"]["message"].stringValue                
            }
        }
        print(self.loginToken)

        if (!self.loginToken.isEmpty) {

            if ((!self.loginToken.contains("[6]")) && (!self.loginToken.contains("Failed"))) {
                UserDefaults.standard.setValue(self.loginToken, forKey: "saved_token")
                print(self.loginToken)        
        } else {
                if (self.loginToken.contains("Access denied")) {
                    self.loginToken = "Access denied"
                    print(self.loginToken)
                } else if (self.loginToken.contains("Failed")) {
                    self.loginToken = "Connection timeout"
                } else if (self.loginToken.contains("[6]")) {
                    DispatchQueue.main.async {
                        AlertController.showErrorWith(title: "Error", message: "Wrong username or password", controller: param3) {

                        }
                    }
                    self.loginToken = "Login Error"
                    print(self.loginToken)
                }        
            }
        }
        self.loginToken = ""
        complete() // moved here to be called after Json().login finished
    }
    //complete()
}

Upvotes: 1

Ram
Ram

Reputation: 969

You need to call the finishLoggingIn() function when the response of performLogin from api come

duom.JsonResult(param1: userName, param2: password, param3: self){ () -> () in
self.finishLoggingIn()
}}

Upvotes: 1

Related Questions