为什么函数会提前返回结果?

时间:2019-05-11 15:55:34

标签: swift

在appDelegate中,我将检查用户是否通过userAuthorizedCheck()功能得到了授权。根据结果​​,将其重定向到一个或另一个stroyBoard。 userAuthorizedCheck()仅在服务器应答后才返回结果。问题是,如果我将最后一个completion(false)留在userAuthorizedCheck()中,则它首先返回false,然后对其进行检查。即使检查成功,也同样会先发送completion(false),然后将重定向发送到“授权”情节提要。

但是,如果我删除了最后一个completion(false),则会得到Thread 1: signal SIGABRT,与之相反的func应用程序()。检查userAuthorizedCheck()后触发print (tempToken)。如果我设置了断点,则可以在userAuthorizedCheck ()函数中看到,最后一个completion (false)首先起作用。

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

    }

登录(在另一个快速文件中):

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()
}

我希望用户Authorized Check ()函数仅在服务器响应后才发送结果。

1 个答案:

答案 0 :(得分:0)

在返回didFinishLaunchingWithOptionstrue之前,您不能false中等待进行异步操作。

一种选择是返回true并在服务器响应后加载情节提要

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
}

并在userAuthorizedCheck

中删除此行

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

因为它会立即完成,这是不希望的。