如何使用回调在Swift中进行异步调用,以便主UI不挂起?

use*_*716 2 callback asynccallback ios parse-platform swift

我正在尝试进行异步调用(到Parse)并且在调用期间我希望我的主UI被挂起.

下面是我试图调用我的ViewController的函数.下面的函数是我在ViewController中使用的代码.

在行sleep(4)行中,ViewController的主UI LoginVC确实卡住了.我没有正确使用异步调用的回调吗?

class Utils {

func logIntoWebService(uname: String, pwd: String, completion: ((result:Bool?) -> Void)!) {

    PFUser.logInWithUsernameInBackground(uname, password:pwd) {
        (user, error) -> Void in

        if error == nil {
            if user != nil {
                // Yes, User Exists

                //UI IS STUCK DURING THIS SLEEP(10)
                sleep(10)

                completion(result: true)

            } else {
                completion(result: false)
            }
        } else {

            completion(result: false)

        }

    }
}

}
Run Code Online (Sandbox Code Playgroud)

我从我的ViewController调用上面的函数.下面是来自我的ViewController的调用

class LoginVC: UIViewController {

var mUtils: Utils = Utils()

mUtils.loggedInStatus({ (result) -> Void in
        println("Response from logInToParse = " + String(stringInterpolationSegment: result))

    })

}
Run Code Online (Sandbox Code Playgroud)

Ica*_*aro 6

你在后台线程和完成处理程序之间混淆了.

logInWithUsernameInBackground是一个在后台运行的异步函数,但是在完成处理程序中运行的所有代码都在主线程中运行:

 completion: ((result:Bool?) -> Void)!) {//The code here runs in the main thread}
Run Code Online (Sandbox Code Playgroud)

所以基本上从你的应用程序开始与Parse.com通信的时间开始,直到结果返回,该代码在后台线程中异步运行,当它完成并且你的应用程序收到它在主要完成块中运行的响应时线.

现在假设您真的想在完成块中在后台运行一些代码,而不是使用类似的东西:

let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
    println("Now this code will run in the background thread")
})
Run Code Online (Sandbox Code Playgroud)

所有新的服务质量等级是:

QOS_CLASS_USER_INTERACTIVE
QOS_CLASS_USER_INITIATED
QOS_CLASS_UTILITY
QOS_CLASS_BACKGROUND
Run Code Online (Sandbox Code Playgroud)

或者在你的情况下:

PFUser.logInWithUsernameInBackground(uname, password:pwd) {
    (user, error) -> Void in
    if error == nil {
        if user != nil {
            // Yes, User Exists

            let qualityOfServiceClass = QOS_CLASS_BACKGROUND
            let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
            dispatch_async(backgroundQueue, {
                sleep(10)
            })
            completion(result: true)

        } else {
            completion(result: false)
        }
    } else {

        completion(result: false)
    }
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅Apple文档