【问题标题】:Performing an asynchronous task within a synchronous call在同步调用中执行异步任务
【发布时间】:2017-01-11 12:28:17
【问题描述】:

我想注册一个异步执行的用户。但是,调用函数的行为是同步的,因为只有在成功创建用户后程序才应该继续。 目前的实现是:

class SignUp: NSObject {

    // ...

    func signUpUser() throws -> Bool {
        guard hasEmptyFields() else {
            throw CustomErrorCodes.EmptyField
        }

        guard isValidEmail() else {
            throw CustomErrorCodes.InvalidEmail
        }

        createUser( { (result) in
            guard result else {
                throw CustomErrorCodes.UserNameTaken
            }
            return true // Error: cannot throw....
        })
    }


    func createUser( succeeded: (result: Bool) -> () ) -> Void {
        let newUser = User()
        newUser.username = username!
        newUser.password = password!

        // User is created asynchronously
        createUserInBackground(newUser, onCompletion: {(succeed, error) -> Void in
            if (error != nil) {
                // Show error alert
            } else {
                succeeded(result: succeed)
            }
        })

    }

}

在 ViewController 中,注册的启动方式如下:

do {
    try signup.signUpUser()
} catch let error as CustomErrorCodes {
    // Process error
}

但是,这不起作用,因为createUser 不是一个抛出函数。如何确保signUpUser() 仅在成功创建新用户时返回true?

【问题讨论】:

    标签: ios swift asynchronous closures


    【解决方案1】:

    你说:

    在 ViewController 中,注册的启动方式如下:

    do {
        try signup.signUpUser()
    } catch let error as CustomErrorCodes {
        // Process error
    }
    

    但不要。这不是异步的工作方式。整个想法是您不要等待。如果你在等待,它不是异步的。这意味着你正在阻止,而这正是你不能做的。

    相反,安排在异步过程结束时回调。那时你会听到事情成功与否。查看下载任务委托的结构:

    https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSessionDownloadTask_class/

    下载任务回调到委托中,让它知道我们是否成功完成。这就是您希望与异步任务建立的关系。你想成为那个代表。

    【讨论】:

    • 这是个好建议。当我使用委托时,它就像一个魅力!但是,在什么情况下最好使用闭包(例如调用 signUpUser),因为这也会使任务异步?
    • 传递回调函数的好处是当你事先不知道要回调什么函数时!
    • 有道理!
    【解决方案2】:

    你需要调整你的想法。与其尝试编写需要等待异步事件的同步方法,不如编写一个接受完成闭包的方法。该方法将立即返回,但是一旦异步过程完成,它就会疯狂地调用完成闭包。当你调用这样的方法时,你会在 incompletion 闭包中传递代码,一旦工作完成就会被调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多