Error Handling with Alamofire in Swift 2 - ios

Hi I am practising some code, my code is fine with case .Success(let value): and it is displaying alert but will case .Failure(let error): display alert with The 4xx class of status code?
Alamofire.request(.GET, URL).responseJSON { (response) -> Void in
if let value = response.result.value {
let json = JSON(value)
switch response.result {
case .Success(let value):
let name = json["name"].string
if let nothing = name {
self.alertMessage(message: "Name not Found")
} else {
self.alertMessage(message: "Name Found")
}
case .Failure(let error):
self.alertMessage(message: "Error 4xx / 5xx")
}

You can use validate to check status codes:
Alamofire.request(.GET, URL)
.validate() // or, if you just want to check status codes, validate(statusCode: 200..<300)
.responseJSON { response in
switch response.result {
case .Success(let value):
let json = JSON(value)
if let name = json["name"].string {
self.alertMessage(message: "Name Found: \(name)")
} else {
self.alertMessage(message: "Name not Found")
}
case .Failure(let error):
self.alertMessage(message: "Error 4xx / 5xx: \(error)")
}
}
Or, in Swift 3:
Alamofire.request(url)
.validate() // or, if you just want to check status codes, validate(statusCode: 200..<300)
.responseJSON { response in
switch response.result {
case .success(let value):
let json = JSON(value)
if let name = json["name"].string {
self.alertMessage(message: "Name Found: \(name)")
} else {
self.alertMessage(message: "Name not Found")
}
case .failure(let error):
self.alertMessage(message: "Error 4xx / 5xx: \(error)")
}
}
Also note that you should probably move the examination of response.result.value to inside the Success section (or just grab the value passed there). Also, the determination of whether name is found was backwards.

Related

Swift: Alamofire: e_invalid_json

I'm working on a company project who use Alamofire to connect to a Dittofi API.
I'm getting a 0 status code and a weirdly null output. Heres the code (I can only release this as per my NDA):
self.manager.upload(multipartFormData: {
multipartFormData in
for (key, value) in params{
multipartFormData.append(value.data(using: .utf8)!, withName: key)
}
}, to: createAssignmentURL, encodingCompletion: {
(result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON {
response in
switch response.result {
case .success(let j):
let json = JSON(j)
print("JSON: ", json)
let message = json["statusMessage"].stringValue
let status = json["statusCode"].intValue
let data = json["data"]
if status == 200{
completion(message,"",status)
}else{
let errorMessage = data["error_msgs"].stringValue
self.reportError(message: errorMessage)
completion(errorMessage,"",status)
}
case .failure(let error):
if error._code == NSURLErrorTimedOut {
completion(App.CONNECTION_TIMEOUT,"",App.STATUS_TIMEOUT)
}
else if error._code == NSFileNoSuchFileError {
completion(App.INVALID_RESPONSE,"",App.STATUS_INVALID_RESPONSE)
}
else {
completion(App.INVALID_RESPONSE,"",App.STATUS_INVALID_RESPONSE)
}
}
}
case .failure(let error):
if error._code == NSURLErrorTimedOut {
completion(App.CONNECTION_TIMEOUT,"",App.STATUS_TIMEOUT)
}
else if error._code == NSFileNoSuchFileError {
completion(App.INVALID_RESPONSE,"",App.STATUS_INVALID_RESPONSE)
}
else {
completion(App.INVALID_RESPONSE,"",App.STATUS_INVALID_RESPONSE)
}
}
})
Heres the output:
JSON: {
"data" : null,
"error" : {
"message" : "",
"param" : "",
"code" : "e_invalid_json"
}
}
I'm certain something is wrong with the way I post but I cant seem to figure it out. I also get a 0 status code which apparently means that the response is empty. Is this a problem with my code or the API?

how to get the response JSON in swift

I got a response from my Alamofire post request. I want to get the Status code from the response.
Here in the code:
case .success(let upload, _, _):
upload.responseJSON { response in
print(response.result.value!)
}
Here is the response looks like:
The value property of the response's result is a dictionary. You can extract status like this:
let json = response.result.value as? [String: Any]
if let status = json?["status"] as? Int {
print(status)
}
Use responseDecodable in Alamofire 5 with Codable Structure
Replace responseJSON with responseDecodable.
.responseDecodable { (response: AFDataResponse<ProfileModel>) in
switch response.result {
case .success(let profileModel):
switch profileModel.status {
case 200:
print("success")
case 101:
print("sessionExpire")
default:
print("default")
}
case .failure(let error):
print("failure")
}
}
ProfileModel
struct ProfileModel: Codable {
let status: Int
let type: String
let data: ProfileDataModel
}
struct ProfileDataModel: Codable {
let ImagePath: String
let ThumbImagePath: String
}

"'isSuccess' is inaccessible due to 'internal' protection level", AlamoFire not working like before

Im using alamoFire on swift but i came across this problem: "isSuccess' is inaccessible due to 'internal' protection level".
I have tried this and i have also tried this,
here is my code:
AF.request(jsonURL, method: .get, parameters: parameters).responseJSON { (response) in
if response.result.isSuccess { //problem is here
print("Got the info")
print(response)
let flowerJSON : JSON = JSON(response.result.value!)
let list = flowerJSON["..."]["..."]["..."].stringValue
print(list)
}
}
result is now of the built-in Result enum type, which means you can do pattern matching on it. Your code can be rewritten as:
AF.request("", method: .get, parameters: [:]).responseJSON { (response) in
if case .success(let value) = response.result {
print("Got the info")
print(response)
let flowerJSON : JSON = JSON(value)
...
}
}
Use a switch statement if you want the error case as well:
switch response.result {
case .success(let value):
// ...
case .failure(let error):
// ...
}

Alamofire receive and parse an array of strings swift

I getting the result as an array of strings like this
["India","America","Australia","China","Russia"]
And I'm using Alamofire to get the response using code. There's no error, but I got the result as null. Please help in parsing this.
sessionManager?.request(strURL, method: method, parameters: params, encoding: encoding , headers: headers).responseJSON { (response) in
switch response.result {
case .success:
let resJson = JSON(response.result.value!)
success(resJson)
break
case .failure(let error):
failure(error as NSError)
break
}
}
Try this:
if let responseData = response.result.value{
let responsevalue = responseData as? [String]
}
For anyone looking for another derived answer, just put this chunk of code after Alamofire.request(...):
.responseJSON(completionHandler: { (response) in
switch response.result{
case .success(let value):
// Here is your array of String
let arrayOfStrings = value as? [String]
case .failure(let error):
// Some code when error happens...
print(error.localizedDescription)
}
})
This solution using SwiftyJSON:
.responseJSON(completionHandler: { (response) in
switch response.result{
case .failure(let error):
print(error.localizedDescription)
case .success(let res):
let json = JSON(res)
let res = json["result"]
var models = [String]()
if let models1 = company["models"].array {
for model in models1 {
guard let mod = model.string else { return }
models.append(mod)
}
}
}
})

How to make a good pattern to control multiple requests dependency by using Alamofire? Such as request2 need request1's response

I use Alamofire to send multiple requests at the same time. But the request A need request B's response named token. I will give a example :
var token = "111111111111"
let URLString1 = "http://httpbin.org/get?token=\(token)"
Alamofire.request(.GET, URLString1, parameters: nil, encoding:.JSON).responseJSON { response in
switch response.result {
case .Success(let JSON):
print("http1: \(JSON)")
token = "22222222222"
case .Failure(let error):
print("Request failed with error: \(error)")
}
}
//I want to wait for request1's response and get the new token value.
let URLString2 = "http://httpbin.org/get?token=\(token)"
Alamofire.request(.GET, URLString2, parameters: nil, encoding:.JSON).responseJSON { response in
switch response.result {
case .Success(let JSON):
print("http2: \(JSON)")
print("token: \(token)")
case .Failure(let error):
print("Request failed with error: \(error)")
}
}
I don't want to put request2 in request1's success.
So now my solution is: I give a variable named tokenChange.I have a array to store all the request that need the token. When the token is changed , I send them one by one from the array. But this solution is not elegant.
So is there a good pattern to control this ?
I find this method dispatch_semaphore_signal.It can solve my problem. So any other way ?
var token = "111111"
let group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) { () -> Void in
let semaphore = dispatch_semaphore_create(0)
//token is 111111
let URLString = "http://httpbin.org/get?token=\(token)"
Alamofire.request(.GET, URLString, parameters: nil, encoding:.JSON).responseJSON { response in
switch response.result {
case .Success(let JSON):
print("http1: \(JSON)--class:")
token = "222222"
print("\n")
dispatch_semaphore_signal(semaphore)
case .Failure(let error):
print("Request failed with error: \(error)")
}
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
//token is 222222
let URLString2 = "http://httpbin.org/get?token=\(token)"
Alamofire.request(.GET, URLString2, parameters: nil, encoding:.JSON).responseJSON { response in
switch response.result {
case .Success(let JSON):
print("http2: \(JSON)--class:")
print("\n")
print ("token is:\(token)")
case .Failure(let error):
print("Request failed with error: \(error)")
}
}
//token is 2222222
let URLString3 = "http://httpbin.org/get?token=\(token)"
Alamofire.request(.GET, URLString3, parameters: nil, encoding:.JSON).responseJSON { response in
switch response.result {
case .Success(let JSON):
// token = (JSON["args"]!!["value"]) as! String
print("http3: \(JSON)--class:")
print("\n")
print ("token is:\(token)")
case .Failure(let error):
print("Request failed with error: \(error)")
}
}
}
dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) { () -> Void in
NSLog("finish");
}
you need to execute the second url string inside the first request because the response will came in background thread so your code will be like this:
var token = "111111111111"
let URLString1 = "http://httpbin.org/get?token=\(token)"
Alamofire.request(.GET, URLString1, parameters: nil, encoding:.JSON).responseJSON { response in
switch response.result {
case .Success(let JSON):
print("http1: \(JSON)")
token = "22222222222"
case .Failure(let error):
print("Request failed with error: \(error)")
}
let URLString2 = "http://httpbin.org/get?token=\(token)"
Alamofire.request(.GET, URLString2, parameters: nil, encoding:.JSON).responseJSON { response in
switch response.result {
case .Success(let JSON):
print("http2: \(JSON)")
print("token: \(token)")
case .Failure(let error):
print("Request failed with error: \(error)")
}
}
}

Resources