异步调用后无法刷新UI

时间:2016-06-16 20:08:42

标签: ios swift multithreading asynchronous swift2

我想做什么:我有一个登录屏幕,用户填写用户名和密码,然后按下登录按钮。完成对服务器的异步调用以检查用户是否已注册且密码是否正常,如果是(异步功能将bool设置为yes),则对下一个视图控制器执行segue。很简单,我尝试了很多方法,但总是遇到同样的问题,主线程运行shouldPerformSegueWithIdentifier方法,执行异步调用并在后台线程之前检查全局bool var(默认为false)已更新它,因此不执行segue,因为全局变量设置为true AFTER。只有当我使用sleep(1)时,UI才会刷新,但我不想使用它。有没有办法在没有睡觉的情况下做到这一点?我运行的每个方法都有一个完成处理程序 我不知道如何将主要与后台线程同步。我已经读过它可以从异步调用更新UI,所以这应该是可行的。我已经找了一段时间的问题并尝试了很多代码片段,但仍然没有找到解决我问题的方法。 这是我到目前为止的代码:

    override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {

    let apiCall = webApi()

    dispatch_async(dispatch_get_main_queue()) {

        apiCall.callCheckIsUserLogged(nil, password : self.passwordField.text, email: self.mailField.text){ (ok) in
        }
    }
//sleep(1) if I uncomment this, my method works because it will return true
    return userIsLogged
}

apiCall.callCheckIsUserLogged()

typealias successClosure = (success : Bool) -> Void
    //Make a call to check if the user exist, server returns json with success or failure
func callCheckIsUserLogged(username: String?, password : String?, email: String?,completed : successClosure){

    userApiCallUrl = "http://apiurl.com/users/login"

    let call = asyncCallClass()
    call.doAsyncCallWithParams(userApiCallUrl, calltype: "POST", username: username, pass: password, mail: email){ (success) in
        completed(success: true)
    }

}

call.doAsyncCallWithParams()代码:

internal typealias completion = (success : Bool) -> Void
private var flagCompletion : Bool = false

        //Handle async class with this method
//var callType is aditioned everytime an arg is not passed nil.
//callType == 3 it is a call to check if user is logged
//callType == 2 is a call to register a new user
func doAsyncCallWithParams(url : String, calltype : String, username : String?, pass : String?, mail : String?, completed : completion){

    var callType : Int = 0


    //Set Async Url
    setUrl(url)

    //Set Post Params
    if let user : String = username{
        self.username = "username=\(user)"
        callType += 1
    }
    if let password : String = pass{
        self.password = "password=\(password)"
        callType += 1
    }
    if let mail : String = mail{
        self.email = "email=\(mail)"
        callType += 1
    }

    //register a new user
    if(callType == 3){
        paramString = "\(self.username)&\(self.password)&\(self.email)"

    }
    //check if user is logged, send email and password
    if(callType == 2){
        paramString = "\(self.email)&\(self.password)"
    }

    //Do call
    callWithCompletionHandler { (success) in
        self.flagCompletion = true
        completed(success: self.flagCompletion)
    }
}

callWithCompletionHandler()代码:

private typealias completionAsyncCall = (success : Bool) -> Void
    private func callWithCompletionHandler(completed : completionAsyncCall){
        asyncJson.removeAllObjects()

        //Set async call params
        let request = NSMutableURLRequest(URL: NSURL(string: self.url!)!)
        request.HTTPMethod = "POST"
        let trimmedPostParam : String = self.paramString!.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())

        request.HTTPBody = trimmedPostParam.dataUsingEncoding(NSUTF8StringEncoding)

        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
            guard error == nil && data != nil else {
                // check for fundamental networking error
                print("error=\(error)")
                return
            }
            if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
                // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(response)")
            }

            let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)


            let result : AnyObject = responseString!.parseJSONString!

                if let nsMutableResult = result as? NSMutableArray{
                    print("NSMutableArray")
                }
                if let nsDictResult = result as? NSMutableDictionary{
                    self.parseMutableDictionary(nsDictResult)
                }


            self.flag = true  // true if download succeed,false otherwise
            completed(success: flagAsyncCall!)
        }
        task.resume()
    }

1 个答案:

答案 0 :(得分:0)

在登录按钮上按下呼叫:

apiCall.callCheckIsUserLogged(nil, password : self.passwordField.text, email: self.mailField.text){ (ok) in
  if ok {
     self.performSegueWithIdentifier("Identifier", sender: self)
  } else {
    print("User not logged in")
   }
}

因为如果用户登录了,您的callCheckIsUserLogged方法已经返回。

internal typealias completion = (success : Bool) -> Void