I'm using xcode 8, swift 3 and AWSCognitoIdentityProvider 2.4.9. When you try to do something like:
pool.signUp(username,
password: password,
userAttributes: userAttributes,
validationData: validationData)
.continue { (task: AWSTask<AWSCognitoIdentityUserPoolSignUpResponse>) -> Any? in
DispatchQueue.main.async {
if let e = task.error {
print("error: \(e)")
} else {
let response = task.result
print("response: \(response)")
}
return nil
}
}
Xcode throws this error: Ambiguous use of 'continue'. This are the methods that swift 3 translates from objc:
open func `continue`(_ block: AWSCore.AWSContinuationBlock) -> AWSTask<AnyObject>
open func `continue`(_ block: AWSCore.AWSContinuationBlock, cancellationToken: AWSCancellationToken?) -> AWSTask<AnyObject>
open func `continue`(with executor: AWSExecutor, with block: AWSCore.AWSContinuationBlock) -> AWSTask<AnyObject>
open func `continue`(with executor: AWSExecutor, block: AWSCore.AWSContinuationBlock, cancellationToken: AWSCancellationToken?) -> AWSTask<AnyObject>
open func `continue`(successBlock block: AWSCore.AWSContinuationBlock) -> AWSTask<AnyObject>
open func `continue`(successBlock block: AWSCore.AWSContinuationBlock, cancellationToken: AWSCancellationToken?) -> AWSTask<AnyObject>
open func `continue`(with executor: AWSExecutor, withSuccessBlock block: AWSCore.AWSContinuationBlock) -> AWSTask<AnyObject>
open func `continue`(with executor: AWSExecutor, successBlock block: AWSCore.AWSContinuationBlock, cancellationToken: AWSCancellationToken?) -> AWSTask<AnyObject>
I try to do this:
typealias SignUpContinueClosure = (AWSTask<AWSCognitoIdentityUserPoolSignUpResponse>) -> (Any?)
let signUpContinueClosure: SignUpContinueClosure = { (task) in
DispatchQueue.main.async {
if let e = task.error {
print("error: \(e)")
} else {
let response = task.result
print("response: \(response)")
}
}
return nil
}
pool.signUp(username,
password: password,
userAttributes: userAttributes,
validationData: validationData)
.continue(signUpContinueClosure)
It compiles but the closure is never executed, also, adding a breakpoint into the closure is never triggered. Any ideas?. Thanks in advance
I've fix it from:
continue { ... }
To:
continue({ ... })
@beeth0ven indeed, it works, but still this ambiguity about method names is pretty annoying, :(
@nebiros Yes Swift 3.0 has a huge update.
@beeth0ven also, the continue block is skipped, is never triggered, I add .waitUntilFinished and it works but doesn't seems right
@nebiros I've this code works for me:
func signUp() {
title = "Signing Up..."
let attributes = [
AWSCognitoIdentityUserAttributeType(name: "phone_number", value: phoneTextField.text),
AWSCognitoIdentityUserAttributeType(name: "email", value: emailTextField.text),
]
pool.signUp(usernameTextField.text!, password: passwordTextField.text!, userAttributes: attributes, validationData: nil)
.continue({ task in
print("task.error", task.error)
print("task.result", task.result)
switch (task.error, task.result) {
case let (error?, _):
DispatchQueue.main.async { self.title = "Fail To Sign Up..." }
print(error.localizedDescription)
case let (_, result?) where result.user.confirmedStatus != .confirmed :
DispatchQueue.main.async {
self.performSegue(withIdentifier: "ConfirmCode", sender: result.codeDeliveryDetails?.destination)
}
default:
DispatchQueue.main.async { self.title = "Succeed to sign up." }
}
return nil
})
}
@beeth0ven hum, need to do the same in the app env, I'm doing this as a unit test, :)
There is a lot to do when update to Swift 3.0. :)
@nebiros Man, I'm having that same issue where the code ignores the .continue block. What did u do to fix it?
`
self.pool.signUp(userNameChosen, password: senhaTextField.text!, userAttributes: attributes, validationData: nil).continue({ (task: AWSTask
if task.error != nil { //ocorreu erro
let alert:UIAlertController = UIAlertController(title: "Error", message: task.error?.localizedDescription, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
} else { //no error
let response:AWSCognitoIdentityUserPoolSignUpResponse = task.result! as AWSCognitoIdentityUserPoolSignUpResponse
self.user = response.user
if response.userConfirmed as! Int != AWSCognitoIdentityUserStatus.confirmed.rawValue { //not confirmed
//setup para mandar atraves de Segue
self.sentTo = response.codeDeliveryDetails?.destination
self.performSegue(withIdentifier: "confirmSignUp", sender: self)
} else { //user ja esta confirmado - pode acontecer?
print("User ja esta confirmado?")
self.navigationController?.popToRootViewController(animated: true) //back to login
}
}
return nil
})`
@Fernandomr88 try to change this: (task: AWSTask) -> Any? to (task) -> Any? or use a generic: (task: AWSTask<AWSCognitoIdentityUserPoolSignUpResponse>) -> Any?, AWSTask needs a generic.
@nebiros Didn't work...the code inside that continue won't run. You said you fixed by using waitUntilFinished. Could you post an example?
@Fernandomr88 I did this:
let task = pool.signUp(username,
password: password,
userAttributes: userAttributes,
validationData: validationData)
XCTAssertNotNil(task)
let exp = expectation(description: "signUp request expectation")
task.continue(with: AWSExecutor.default(), with: { (task: AWSTask<AWSCognitoIdentityUserPoolSignUpResponse>) -> Any? in
print("signUp task: \(task)")
if let e = task.error {
XCTFail(e.localizedDescription)
} else {
let response = task.result
print("response: \(response)")
let user = response?.user
XCTAssertNotNil(user)
XCTAssertEqual(username, user?.username)
}
exp.fulfill()
return nil
}).waitUntilFinished()
waitForExpectations(timeout: 5.0, handler: nil)
I add waitUntilFinished() but because I needed for this unit test
@nebiros Not even that..If I try to access unauthenticated I can login just fine, but when I try to sign up that code inside that {} wont execute! This is really really anoying!
I have even tried to separate like you did and still code wont execute! Any other ideas? Swift 3 is giving me a lot of trouble...
`
let task = self.pool.signUp(userNameChosen, password: senhaTextField.text!, userAttributes: attributes, validationData: nil)
task.continue(with: AWSExecutor.default(), with: { (task) -> Any? in
if task.error != nil { //ocorreu erro
let alert:UIAlertController = UIAlertController(title: "Error", message: task.error?.localizedDescription, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
} else { //nao ocorreu erro
print("no error")
}
return nil
}).waitUntilFinished()
`
I even started to think it could be a problem in my connection with AWS, since it will only execute when the Task is finished. But when unauthenticated, i connect successfully to AWS.
Has anyone worked past Swift 3.0 protocol adherence for AWSCognitoIdentityPasswordAuthentication or AWSCognitoIdentityMultiFactorAuthentication. I have what I would expect to be the functions implemented per the protocol, but Xcode is telling me I'm not conforming.
extension SignInViewController: AWSCognitoIdentityPasswordAuthentication {
func getPasswordAuthenticationDetails(authenticationInput: AWSCognitoIdentityPasswordAuthenticationInput, passwordAuthenticationCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>) {
self.passwordAuthenticationCompletion = passwordAuthenticationCompletionSource
}
func didCompletePasswordAuthenticationStepWithError(error: NSError?) {
if let error = error {
DispatchQueue.main.async {
UIAlertView(title: error.userInfo["__type"] as? String,
message: error.userInfo["message"] as? String,
delegate: nil,
cancelButtonTitle: "Ok").show()
}
}
}
}
UPDATE 1: I got a little further today: turns out Xcode wasn't picking up the renamed functions in the protocol definitions. They are "didCompleteStepWithError" and "getDetails" instead. This new code block is as follows:
```
extension SignInViewController: AWSCognitoIdentityPasswordAuthentication {
func getDetails(_ authenticationInput: AWSCognitoIdentityPasswordAuthenticationInput, passwordAuthenticationCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>) {
self.passwordAuthenticationCompletion = passwordAuthenticationCompletionSource as! AWSTaskCompletionSource<AnyObject>
}
func didCompleteStepWithError(_ error: Error?) {
if let error = error as? NSError {
DispatchQueue.main.async {
UIAlertView(title: error.userInfo["__type"] as? String,
message: error.userInfo["message"] as? String,
delegate: nil,
cancelButtonTitle: "Ok").show()
}
}
}
}
````
I have had challenges too with error.userInfo how to do that in Swift 3. I just solved that by using error.debugDescription and checking if that contains certain exception texts. That is not good way but I could not find anything else. E.g:
`
func didCompleteStepWithError(_ error: Error?) {
var descr = error.debugDescription
if descr.contains("NotAuthorizedException") {
if descr.contains("User is disabled") {
descr = "User is disabled"
} else {
descr = "Incorrect username or password."
}
} else if descr.contains("UserNotFoundException") {
descr = "Incorrect username or password."
} else if descr.contains("UserNotConfirmedException") {
descr = "User is not confirmed. Please confirm the user first before logging in."
} else if (descr.contains("offline")) {
descr = "Internet connection not available"
}
if error != nil {
DispatchQueue.main.async(execute: {
self.alertInfo(title: "Error with login", descr)
})
}
}
func alertInfo(title:String, _ message:String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
`
@jukka-palomaki I got this working today in fact. I'm not sure if this is stylistically correct in Swift 3, but I got my code to work by using:
if let error = error as? NSError
This will allow userInfo to show up. I have read somewhere else that Swift 3 doesn't want you to use statements like this, but the code works...
Please use version 2.5.0 of the SDK. Swift name translations have been updated. You may use XCode's autocomplete feature to see the new method names.
we can resolve issue:
"Value of type 'AWSTask
using following line of code
user.getSession(email, password: password, validationData: [emailAttr!]).continueWith(block: { task in
})
Value of type 'AWSTask<AWSS3TransferUtilityUploadTask>' has no member 'continueWith' issue after pod update in xcode version 11.3.
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = progressBlock
expression.setValue("public-read", forRequestHeader: "x-amz-acl")
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadData(imageData,
bucket: Constants.kS3BucketNameUser,
key: fileName,
contentType: Constants.kContentTypeImage,
expression: expression,
completionHander: completionHandler).continueWith(block: { (task) -> AnyObject? in
if let error = task.error {
DispatchQueue.main.async{
self.appDelegate.helper.hideHUD(self)
_ = EthOSAlertController.alert(Constants.Messages.kAppName, message: error.localizedDescription)
}
}
return nil;
})
@Priyanka-gupta-pcg Any luck on finding an answer?
Most helpful comment
I've fix it from:
continue { ... }To:
continue({ ... })