I'm currently trying to call a prepareForSegue method in an AlamoFire completion handler but it's not being called. Here is my code:
func loginMember (username: String, password: String, completionHandler: (String?, ErrorType?) -> ()) {
let headers = [
"Cache-Control": "no-cache",
"Content-Type": "application/json"
]
let parameters: [String: AnyObject] = [
"grant_type" : "password",
"username" : username,
"password" : password,
]
Alamofire.request(.POST, "\(baseURL)/oauth2/token", parameters: parameters, encoding: .JSON, headers: headers)
.validate()
.responseJSON { response in
switch response.result {
case .Success:
guard let value = response.result.value else {
completionHandler(nil, response.result.error)
return
}
let swiftyJsonVar = JSON(value)
accessToken = swiftyJsonVar["access_token"].stringValue
print("This is the login response:\(swiftyJsonVar)")
case .Failure(let error):
print("Sorry there was an error: \(error)")
return
}
}
}
This is what it looks like when called:
loginMember(username, password: password, completionHandler: { error in
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("loginToHomeSegue", sender: self)
}
}
)
Any ideas as to why the performSegueWithIdentifier isn't being called?
You're only calling your completion handler in the case where you enter your guard statement. You need to add calls for the case where you get your access token and your error case.
Alamofire.request(.POST, "\(baseURL)/oauth2/token", parameters: parameters, encoding: .JSON, headers: headers)
.validate()
.responseJSON { response in
switch response.result {
case .Success:
guard let value = response.result.value else {
completionHandler(nil, response.result.error)
return
}
let swiftyJsonVar = JSON(value)
accessToken = swiftyJsonVar["access_token"].stringValue
print("This is the login response:\(swiftyJsonVar)")
// Got the token, call handler
completonHandler(accessToken, nil)
case .Failure(let error):
print("Sorry there was an error: \(error)")
// Got an error, call handler
completionHandler(nil, error)
return
}
}
Related
responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)
What does it mean?
struct URLService {
static var language = LocalizationService.shared.language.userSymbol.uppercased()
static let baseUrl = "http://192.168.9.42:5080"
static func checkLogin(login: String, password: String) {
let parametrs: Parameters = [
"language": "RU",
"password": "password",
"username": "login"
]
let url = "\(URLService.baseUrl)/someURL"
let authRequest = AF.request(url,
method: .post,
parameters: parametrs,
encoding: URLEncoding(destination: .queryString))
authRequest.responseData { (response) in
switch(response.result) {
case .success(_):
print("\(response) check response")
case .failure(let error):
print("\(error) check error")
}
}
}
}
U will help me, if show me other cases with this error and your repairing.
For me was right:
let authRequest = AF.request(url,
method: .post,
parameters: parameters,
encoding: JSONEncoding.default)
authRequest.responseString { response in
switch response.result {
case .success(let value):
print("succes")
case .failure(let error):
print("Error while querying database: \(String(describing: error))")
}
}
JSONEncoding + responseString(Just for more convenience)
This question already has answers here:
Returning data from async call in Swift function
(13 answers)
Closed 4 years ago.
I'm trying to verify a login and return a boolean value from my function accordingly, but my return statement keeps getting executed before the web service function is completed, even if I use an async method. I am using both Alamofire and SwiftyJSON.
I'm attaching my code below. Any help would be appreciated!
Thanks.
func checkUs (name: String, password: String) -> Bool
{
bool authen = false
DispatchQueue.global(qos: .userInitiated).async {
let jsonDic : [String: String] = ["email": name, "pass": password]
Alamofire.request("enter URL here", method: .post, parameters: jsonDic, encoding: JSONEncoding.default, headers: nil).responseJSON { (response) in
switch(response.result) {
case .success(let sentJSON):
let gotJSON = JSON (sentJSON)
print (gotJSON[0]["status"].boolValue)
authen = gotJSON[0]["status"].boolValue
case .failure(let err):
print(err)
}
print ("First ", authen)
}
}
print ("Second", authen)
return authen
//return true
Log Output:
Second false
true
First true
You need completion , also Alamfire runs asynchronously no need for global queue
func checkUs (name: String, password: String,completion: #escaping (_ status: Bool,_ err:Error?) -> Void) {
bool authen = false
let jsonDic : [String: String] = ["email": name, "pass": password]
Alamofire.request("enter URL here", method: .post, parameters: jsonDic, encoding: JSONEncoding.default, headers: nil).responseJSON { (response) in
switch(response.result) {
case .success(let sentJSON):
let gotJSON = JSON (sentJSON)
print (gotJSON[0]["status"].boolValue)
authen = gotJSON[0]["status"].boolValue
completion(authen,nil)
case .failure(let err):
print(err)
completion(authen,err)
}
print ("First ", authen)
}
print ("Second", authen)
}
//
call it like this
self.checkUs(name: "endedName", password: "sendedPassword") { (status, error) in
if let err = error {
}
else
{
}
}
My JSON response in postman looks like this...
{
"success": 1,
"Details": {
"seller_id": "165",
"mobile_no": "9653265987",
"seller_name": "User A",
"seller_email_id": "user#gmail.com",
"company_name": "myCompany",
"category": "Cosmetics",
"otp": "1111"
},
"message": "Seller Already Registered!!!"
}
Now I wanted to give a condition based on whether success is 0 or 1 and so for that I wanted to extract success. Also I want to extract mobile number. But I am not able figure out how to do that.
This is how I am making my Alamofire post request...
Alamofire.request(url, method: .post, parameters: Parameters, encoding: URLEncoding.httpBody, headers: headers)
.responseString { (response) in
if let httpResponse = response.response {
print("error \(httpResponse.statusCode)")
if httpResponse.statusCode == 200 {
//Do something
}
}
}
I did go through similar issues raised by other users...but couldn't find from them an exact solution for my issue...
Try this
Alamofire.request(url, method: .post, parameters: Parameters, encoding: URLEncoding.httpBody, headers: headers)
.responseJSON { (response) in
switch response.result{
case .success(_):
print("Success: \(response)")
let JsonResponse = response.result.value as? [String: Any]
if JsonResponse?["success"] as! Int == 1{
let dict = JsonResponse?["Details"] as! [String : Any]
let mobileNo = dict["mobile_no"] as! String
}
else{
print("Failed")
}
case .failure(let error):
print("Failed: \(error)")
}
}
There are a couple of issues:
Your parameters to request don't look quite right.
the parameters parameter doesn't look right: at best, it's very strange to have a Parameters variable (you should use lower case for variables; and this conflicts with an Alamofire type);
the encoding should be URLEncoding.default. Or, because URLEncoding.default is the default value, you can omit this altogether.
If you want to check for status code, let validate do that for you.
If you're expecting JSON in response, use reponseJSON instead of responseString.
Use if let or guard let with as? to safely unwrap optionals. Do not use as! (unless you are 100% sure that it never could fail ... and when dealing with responses from a remote server, you can never be 100% confident).
Thus:
func performRequest(url: String, parameters: [String: String]?, headers: [String: String]?) {
Alamofire.request(url, method: .post, parameters: parameters, headers: headers)
.validate(statusCode: 200 ..< 300)
.responseJSON { response in
switch response.result {
case .success(let value):
guard let dictionary = value as? [String: Any],
let success = dictionary["success"] as? Int else {
print("success not found")
return
}
guard success == 1 else {
print("web service reported failure")
return
}
guard let details = dictionary["Details"] as? [String: Any] else {
print("Did not find details")
return
}
guard let mobile = details["mobile_no"] as? String else {
print("mobile not found")
return
}
print(mobile)
case .failure(let error):
print("Failed: \(error)")
}
}
}
Or, in your comment below, if you want to goToSignUpScreen() if success was 0, then:
Alamofire.request(url, method: .post, parameters: parameters, headers: headers)
.validate(statusCode: 200 ..< 300)
.responseJSON { response in
switch response.result {
case .success(let value):
guard let dictionary = value as? [String: Any],
let success = dictionary["success"] as? Int else {
print("success not found")
return
}
if success == 0 {
self.goToSignUpScreen()
}
case .failure(let error):
print("Failed: \(error)")
}
}
I need to wait for response.response?.allHeaderFields data before executing function. I've searched the net and didn't quite get how to add "completion handler" to alamofire request. Or if there are any other ways to make the function wait.
#IBAction func comfirmation(sender: UIButton) {
if CodeTextField.text != "" {
print("in comfirmation function")
let comfirmationRequestData = [
"phone" : "\(appDelegate.savedNumber)",
"code" : "\(CodeTextField.text!)"
]
Alamofire.request(.POST,
"http://192.168.214.241:4000/login",
parameters: comfirmationRequestData,
encoding: .JSON).responseJSON {
response in
switch response.result {
case .Success:
let jsonDecrypted = JSON(response.result.value!)
print(jsonDecrypted)
let headerFile = response.response?.allHeaderFields as? [String:String]
print(headerFile)
case .Failure(let error):
print(error)
}
}
print("in comfirmation function. success")
appDelegate.defaults.setValue(appDelegate.savedNumber, forKey: "phoneNumber")
} else {
print("in comfirmation function. failed")
}
}
Use Alamofire like this
func postRequest( urlSuffix : String, params:[String : AnyObject]?, filterParams : [String]?, success: (response: AnyObject!) -> Void, failure: (error: NSError?) -> Void)
{
Alamofire.request(.POST, webServicesURLPrefix + urlSuffix, parameters: params, encoding: .JSON, headers: self.headers)
request?.responseJSON { response in
switch response.result
{
case .Success:
success(response: response.result.value)
case .Failure(let error):
failure(error: error)
}
}
}
Call the method from anywhere as
self.postRequest("do-registration.php", params: params, filterParams: nil, success: { (response) -> Void in
self.afterResponse(response)
}) { (error) -> Void in
failure(error: error)
}
OR you can write a saperate method which you will have to call after the completion.
func afterResponse(responseData : AnyObject)
{
print("Done")
print(responseData)
}
You can cause the operation to be synchronous, but in order to do that you are going to have to use a semaphore for that you set up prior to the Alamofire request, and that you then release within the completion handler. You will wait on the semaphore right after you initiate Alamo fire.
There is a library Alamofire-Synchronous which works using semaphore.
Sample:
//json
let response = Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"]).responseJSON()
if let json = response.result.value {
print(json)
}
My goal is to create a simple function where I pass in a url and it returns me JSON. I have looked around and found little examples of where a completion handler is implemented with Alamofire.
I am also using Swifty Json to help parse it out.
How do I turn what I have here to a function where it returns my Json.
func request() {
Alamofire.request(.GET, API_END_POINT)
.responseJSON {
response in
// swiftyJsonVar is what I would like this function to return.
let swiftyJsonVar = JSON(response.result.value!)
}
}
Swift 3+ and Alamofire 4+
// Call function
myFunction("bodrum") { response in
print(response["yourParameter"].stringValue)
}
// POST
func myFunction(_ cityName:String, completion: #escaping (JSON) -> ()) {
let token = "token"
let parameters = ["city" : cityName]
let headers = ["Authorization": "token"]
let url = URL(string: "url")!
let reqUrl = URLRequest(url: url)
Alamofire.request(reqUrl, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers)
.validate()
.responseJSON { response in
switch response.result {
case .Success:
let jsonData = JSON(data: response.data!)
completion(jsonData)
case .Failure(let error):
MExceptionManager.handleNetworkErrors(error)
completion(JSON(data: NSData()))
}
}
}
Swift 2 and Alamofire 3+
// POST
func myFunction(cityName:String, completion : (JSON) -> ()) {
Alamofire.request(.POST, "url", parameters: ["city" : cityName], encoding: ParameterEncoding.JSON, headers: ["Authorization": "token"])
.validate()
.responseJSON { response in
switch response.result {
case .Success:
let jsonData = JSON(data: response.data!)
completion(jsonData)
case .Failure(let error):
MExceptionManager.handleNetworkErrors(error)
completion(JSON(data: NSData()))
}
}
}
// GET
func myFunction(cityName:String, completion : (JSON) -> ()) {
Alamofire.request(.GET, "url", parameters: ["param1" : cityName], headers: ["Authorization": "token"])
.validate()
.responseJSON { response in
switch response.result {
case .Success:
let jsonData = JSON(data: response.data!)
completion(jsonData)
case .Failure(let error):
MExceptionManager.handleNetworkErrors(error)
completion(JSON(data: NSData()))
}
}
}
// Call function
myFunction("bodrum") { response in
print(response["yourParameter"].stringValue)
}