Taco Taco - 3 months ago 12
Swift Question

Performing an asynchronous task within a synchronous call

I would like to register a user which is performed asynchronous. However, the calling function behaves synchronous since the program should only continue when a user is created successfully.
The current implementation is:

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

}

}


and in a ViewController the signup is initiated as follows:

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


However, this does not work since
createUser
is not a throwing function. How could I ensure that
signUpUser()
only returns true when an new user is created successfully?

Answer

You say:

and in a ViewController the signup is initiated as follows:

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

But don't. That's not how asynchronous works. The whole idea is that you do not wait. If you're waiting, it's not asynchronous. That means you're blocking, and that's just what you mustn't do.

Instead, arrange to be called back at the end of your asynchronous process. That's when you'll hear that things have succeeded or not. Look at how a download task delegate is structured:

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

The download task calls back into the delegate to let it know whether we completed successfully or not. That is the relationship you want to have with your asynchronous task. You want to be like that delegate.