In appDelegate I will check whether the user is authorized through the userAuthorizedCheck() function. Depending on the result, redirect it to one or another stroyBoard. userAuthorizedCheck() should return the result only after the server has answered. The problem is that if i leave the last completion(false) in userAuthorizedCheck(), then it returns false first, and then it is checked. Even if the check was successful, then all the same, completion(false) is sent first and, as a result, the redirect is sent to the Authorization storyboard.

But if I remove the last completion(false), then I get Thread 1: signal SIGABRT, opposite func application (). print (tempToken) is triggered after checking userAuthorizedCheck (). If i put a breakpoint, i can see that in the userAuthorizedCheck () function, the last completion (false) works first.

AppDelegate:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        var storyboardName: String = ""
        userAuthorizedCheck(after: { (succesful) in
            if (succesful == true){
                storyboardName = "Main"

            }else{
                print(false)
                storyboardName = "Authorization"

            }
        })


        let storyboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
        window = UIWindow(frame: UIScreen.main.bounds)
        window!.makeKeyAndVisible()
        window!.rootViewController = storyboard.instantiateInitialViewController()

        return true
    }

    func userAuthorizedCheck(after completion: @escaping (Bool) -> Void) {
        let username : String = UserDefaults.standard.string(forKey: "username") ?? ""
        let password : String = UserDefaults.standard.string(forKey: "password") ?? ""
        let tokenSaved : String = UserDefaults.standard.string(forKey: "token") ?? ""
        var tempToken:String = ""


        //
        if(!username.isEmpty && !password.isEmpty)
        {
            let json: [String: String] = ["username": username, "password": password]


            login(json: json, after: {(status, token, code) in
                if(code == 200 && !token.isEmpty){
                    UserDefaults.standard.setValue(token, forKey: "token");
                    UserDefaults.standard.synchronize();
                    tempToken = token
                    print(tempToken)
                    completion(true)

                }
                else{
                    tempToken = ""
                    completion(false)

                }
            })

        }
        else
        {
            completion(false)
        }
        completion(false)//The problem in this line, as I repent

    }

login(in another swift file):

func login(json:Any, after completion: @escaping (Bool, _ token: String, _ code:Int)  -> Void){
    guard let url = URL(string: ngrok+"/api/auth/token/create")else{return}
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField:"Content-Type")

    guard let httpBody = try? JSONSerialization.data(withJSONObject: json, options: [])else {return}
    request.httpBody = httpBody
    let sessionConfig = URLSessionConfiguration.default
    sessionConfig.timeoutIntervalForRequest = 5.0
    sessionConfig.timeoutIntervalForResource = 60.0
    URLSession(configuration: sessionConfig).dataTask(with: request){(data, response, error) in
        if  error != nil{
            print("server error")
            completion(true, "", 0)
        }
        else if let response = response{
//            print(response)
            if let httpResponse = response as? HTTPURLResponse{
                guard let data = data else{return}
                do{
//                    print(data)
                    if(httpResponse.statusCode == 200){
                        if let json_response = try JSONSerialization.jsonObject(with: data, options: [])as? [String:Any]{
                            if let token = json_response["auth_token"]{
                                print(token as! String)
                                completion(true, "token",httpResponse.statusCode)
                            }
                        }
                    }
                    else if(httpResponse.statusCode == 400)
                    {
                        completion(true, "",httpResponse.statusCode)
                        print("The username or password you entered is incorrect")
                    }
                    else{
                        print("Unknown error")
                        completion(true, "", 0)
                    }
                }
                catch{
                    print("errasd")
                    print(error)
                    completion(true, "", 0)
                }
            }
        }
        }.resume()
}

I want the user Authorized Check () function to send the result only after the server has responded.

1 Answers

0
vadian On Best Solutions

You cannot wait in didFinishLaunchingWithOptions for something asynchronous before returning true or false.

One option is to return true and load the storyboard after the response of the server

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    userAuthorizedCheck(after: { (succesful) in
        let storyboardName = succesful ? "Main" : "Authorization"
        let storyboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
        self.window = UIWindow(frame: UIScreen.main.bounds)
        window!.makeKeyAndVisible()
        window!.rootViewController = storyboard.instantiateInitialViewController()
    })

    return true
}

And delete this line in userAuthorizedCheck

completion(false)//The problem in this line, as I repent

because it completes immediately which is not intended.