Swift - 在恢复执行之前等待登录请求完成的正确方法

时间:2016-02-10 12:29:52

标签: swift api

我有以下代码执行登录Web服务器,检索API令牌,然后允许应用程序继续。执行此代码后,调用函数使用login_result向用户报告他们是否已成功登录或需要重试。

现在,我只是让应用程序睡眠3秒钟,以确保我在继续之前有响应。否则,登录结果处理程序开始执行而没有答案(因为服务器没有时间响应)。

显然,这是一种可怕的做事方式。处理这个问题的正确/迅捷的惯用方法是什么?

func remote_login (email: String, password: String) -> Bool {
    login_result = false
    var jsonResults: NSDictionary = [:]
    let account = Account()
    let url = NSURL(string: "\(base_api_url())/login?email=\(email)&password=\(password)")
    let request = NSMutableURLRequest(URL: url!)

    request.HTTPMethod = "GET"
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    request.addValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")

    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in

        do {
            jsonResults = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
            account.setCredentials(jsonResults)  // we store an API token returned from a successful login; we don't store the users credentials locally
            self.login_result = true
        }
        catch {
            print("\n\n\n Login Error \n\n\n")
        }
    }) // task
    task.resume()
    sleep(3)  //need time for the response to come back...s/b far more elegant way to do this.
    return self.login_result
}

2 个答案:

答案 0 :(得分:1)

使用closure作为函数参数,如下所示:

func remote_login(email: String, password: String, completion((Bool) -> Void)) {

然后,在完成后(在JSON解析之后)调用闭包,如下所示:

self.login_result = true
completion(login_result)

因此,当您使用该功能时,它将如下所示:

remote_login("email", "password", {
    success in

    //Logged in successfully    
}

HTTP请求完成后将调用闭包。

答案 1 :(得分:0)

我最好能看到:

func remote_login (email: String, password: String, myFunctionCompletionHandler: ()->()) -> Bool {
    login_result = false
    var jsonResults: NSDictionary = [:]
    let account = Account()
    let url = NSURL(string: "\(base_api_url())/login?email=\(email)&password=\(password)")
    let request = NSMutableURLRequest(URL: url!)

    request.HTTPMethod = "GET"
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    request.addValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")

    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in

        do {
            jsonResults = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
            // we store an API token returned from a successful login; we don't store the users credentials locally
            account.setCredentials(jsonResults) 
            myFunctionCompletionHandler()
            // is this needed as it's handled by the handler?
            self.login_result = true
        }
        catch {
            myFunctionCompletionHandler()
            print("\n\n\n Login Error \n\n\n")
        }
    }) // task
    task.resume()
    return self.login_result
}

你可能不得不重构一些东西以便更好地处理completionHandler,因为我只是字面上"在"但这应该可以解决问题:)..

只需处理并传递"失败并通过"正确地跨过它:)