Alamofire (json, request, delay) - ios

i have a json request and my problem is that the response from the server does not have time to come and because of this I get an error because I'm working with data (in viewdidload()) which is not yet available. I tried to read about synchronous and asynchronous requests but I don't understand how to do them.
in viewDidLoad() i call my fucn which is call to the my server and i wait a json, after executing the function, I start working with the data that should come , But the code does not wait for the moment when they come and go further. Can I specify a delay or something like that?
Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON {
(response: DataResponse) in
switch(response.result) {
case .success(let value):
let json = JSON(value)
for index in 0 ..< json["items"].count {
let path = json["items"][index]
self.Data.append(ProfileModel())
self.Data[index].name = path["name"].stringValue
self.Data[index].email = path["email"].stringValue
self.Data[index].created = path["created"].double!
self.tableView.reloadData()
}
DispatchQueue.main.async {
}
case .failure(let error):
print(error)
break
}
}.resume()
}

Related

Loop JSON requests to backend (REST API)

I am sending request to the backend (REST API). My task: If the JSON response does not come in the required format, or returns an error, then start the request cycle - 3 attempts, and if these three attempts fail, then exit, else go next (HomePage)
Here is code:
func checkUsers(){
let headers: HTTPHeaders = ["Content-Type" : "application/json"]
NetworkManager.sharedInstance.manager.request("https://restapi.com/user",
method: .get,
parameters: nil,
encoding: JSONEncoding.default,
headers: headers).responseJSON { (response) -> Void in
switch response.result {
case .success(let value):
let response = JSON(value)
print("JSON Response: \(response)")
if response["operation"].stringValue == "loginerror" {
print("Error")
self.showNotRegisteredScreen()
} else {
usersFIO = response["userName"].stringValue
self.didFinishLogin()
}
case .failure(let error):
print("fail to fecth data",error)
self.showErrorScreen()
}
}
Please tell me how to start a request cycle in which to specify three attempts
P.S.: Using Alamofire and SwiftyJson pods
Thanks in advance!
It works for me with Alamofire 5
lazy var manager: Alamofire.Session = {
let configuration = URLSessionConfiguration.default
let retryPolicy = RetryPolicy(retryLimit: 3)
let interceptor = Interceptor(retriers: [retryPolicy])
let manager = Alamofire.Session(configuration: configuration, interceptor: interceptor, serverTrustManager: serverTrustManager, eventMonitors: [CertificateAuthAdapter()])
return manager
}()

getting data from AF.Request response

I need the data from the json response from my Post request call using Alamofire but I cannot access that data for some reason
I tried following along with Alamofire github documentation along with this post get data from AF responseJSON. but neither have helped me.
AF.request("https://mbd.cookcountysupernetwork.com/ap/swift_math_get.asp", method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
print(response)
print("floop")
}
This is what I see when the code runs
success({
Operand = (
{
A = 12;
},
{
B = 25;
}
);
Operation = Multiply;
Result = 300;
})
so I know the json is there, i just need to access the "Result = 300" so I can set a text box to say "300". but I tried many different methods and I cannot access the information I need from response. Also i do not have a response.result.value which is what almost every post I see about this says to use.
You can access the Result value as,
AF.request("https://mbd.cookcountysupernetwork.com/ap/swift_math_get.asp", method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success(let value):
if let json = value as? [String: Any] {
print(json["Result"] as? Int)
}
case .failure(let error):
print(error)
}
}

How to set method, header, parameter in Alamofire 4 and Swift 3

In past version of Alamofire, for send method,header and parameter I used to do like this:
Alamofire.request(.GET, URLRequest, headers:headers, parameters: parameters)
but version 4 and swift 3 is different.
How can I set method, send header & parameter?
The migration guide at Alamofire github explains this very well.
Take a look here:
// Alamofire 3
let parameters: [String: AnyObject] = ["foo": "bar"]
Alamofire.request(.GET, urlString, parameters: parameters, encoding: .JSON)
.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
print("Bytes: \(bytesRead), Total Bytes: \(totalBytesRead), Total Bytes Expected: \(totalBytesExpectedToRead)")
}
.validate { request, response in
// Custom evaluation closure (no access to server data)
return .success
}
.responseJSON { response in
debugPrint(response)
}
// Alamofire 4
let parameters: Parameters = ["foo": "bar"]
Alamofire.request(urlString, method: .get, parameters: parameters, encoding: JSONEncoding.default)
.downloadProgress(queue: DispatchQueue.utility) { progress in
print("Progress: \(progress.fractionCompleted)")
}
.validate { request, response, data in
// Custom evaluation closure now includes data (allows you to parse data to dig out error messages if necessary)
return .success
}
.responseJSON { response in
debugPrint(response)
}
The migration guide explained well, but there are no headers in the example, just to avoid confusions, bellow I add the example of a GET request to add them.
Alamofire.request(URL, method: .get, parameters: parameters, headers: headers)
.validate { request, response, data in
return .success
}
.responseJSON { response in
switch response.result {
case .success:
// do something
break
case .failure(let error):
// handle error
break
}
}
I found this information in here so, go and check it there if you have question related with the headers in the request.

iOS Swift 2 - Alamofire print response value when Failure

I'm using Alamofire for my http requests but I'm not able to get error message from requests that don't pass validation
Alamofire.request(method, url, headers: headers, parameters: parameters, encoding: encoding)
.validate(statusCode: 200..<300)
.responseJSON { response in
switch response.result {
case .Success:
// response.result.value returns JSON
case .Failure(let error):
// response.result.value returns nil
}
}
How can I get data (JSON) if I get error code 400 and others. The API is sending the data in body even if the request was not successful.
As Following SaiCYLi, Only way to get response data is avoid using validate.
See Result.swift in Alamofire.
There is blocker.
public var value: Value? {
switch self {
case .Success(let value):
return value
case .Failure:
return nil
}
}
I wanted comment to you instead of answering. But I have reputation less than 50. Sorry.
just delete your validation of status code
Code:
Alamofire.request(method, url, headers: headers, parameters: parameters, encoding: encoding)
.responseJSON {
response in
let statusCode = response.response.statusCode
switch statusCode {
case 200..<300:
// Success
case 404:
// not found
default:
// something else
}
}

Alamofire returns .Success on error HTTP status codes

I have a pretty simple scenario that I'm struggling with. I'm using Alamofire to register a user on a rest API. The first call to register is successful and the user can log in. The second call, when trying to register with the same email address should result in a HTTP status code 409 from the server. Alamofire, however, returns a .Success with an empty request and response. I have tested this this API with postman and it correctly returns a 409.
Why is Alamofire not returning .Failure(error), where the error has status code info etc?
Here is the call I run with the same input each time.
Alamofire.request(.POST, "http://localhost:8883/api/0.1/parent", parameters: registrationModel.getParentCandidateDictionary(), encoding: .JSON).response(completionHandler: { (req, res, d, e) -> Void in
print(req, res, d, e)
})
From the Alamofire manual:
Validation
By default, Alamofire treats any completed request to be successful,
regardless of the content of the response. Calling validate before a
response handler causes an error to be generated if the response had
an unacceptable status code or MIME type.
You can manually validate the status code using the validate method, again, from the manual:
Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.response { response in
print(response)
}
Or you can semi-automatically validate the status code and content-type using the validate with no arguments:
Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
.validate()
.responseJSON { response in
switch response.result {
case .success:
print("Validation Successful")
case .failure(let error):
print(error)
}
}
If using response, you can check the NSHTTPURLResponse parameter:
Alamofire.request(urlString, method: .post, parameters: registrationModel.getParentCandidateDictionary(), encoding: JSONEncoding.default)
.response { response in
if response.response?.statusCode == 409 {
// handle as appropriate
}
}
By default, 4xx status codes aren't treated as errors, but you can use validate to treat it as an such and then fold it into your broader error handling:
Alamofire.request(urlString, method: .post, parameters: registrationModel.getParentCandidateDictionary(), encoding: JSONEncoding.default)
.validate()
.response() { response in
guard response.error == nil else {
// handle error (including validate error) here, e.g.
if response.response?.statusCode == 409 {
// handle 409 here
}
return
}
// handle success here
}
Or, if using responseJSON:
Alamofire.request(urlString, method: .post, parameters: registrationModel.getParentCandidateDictionary(), encoding: JSONEncoding.default)
.validate()
.responseJSON() { response in
switch response.result {
case .failure:
// handle errors (including `validate` errors) here
if let statusCode = response.response?.statusCode {
if statusCode == 409 {
// handle 409 specific error here, if you want
}
}
case .success(let value):
// handle success here
print(value)
}
}
The above is Alamofire 4.x. See previous rendition of this answer for earlier versions of Alamofire.
if you use validate() you'll loose the error message from server, if you want to keep it, see this answer https://stackoverflow.com/a/36333378/1261547
Here is my code for AlamoFire error catching:
switch response.result {
case .success(let value):
completion(.success(value))
case .failure(var error):
var errorString: String?
if let data = response.data {
if let json = try? (JSONSerialization.jsonObject(with: data, options: []) as! [String: String]) {
errorString = json["error"]
}
}
let error = MyError(str: errorString!)
let x = error as Error
print(x.localizedDescription)
completion(.failure(x))
}
and the MyError class difinition:
class MyError: NSObject, LocalizedError {
var desc = ""
init(str: String) {
desc = str
}
override var description: String {
get {
return "MyError: \(desc)"
}
}
//You need to implement `errorDescription`, not `localizedDescription`.
var errorDescription: String? {
get {
return self.description
}
}
}

Resources