I implemented the following code
AF.request(url, method: .post, parameters: parameter, encoding: JSONEncoding.default).responseData(completionHandler: {response in
print(response)
switch response.result {
case .success:
print(response.result)
let alertVC = self.alertservices.alert(title: "Add Recipe : Basic Level", message: "Your basic level recipe details has been submitted successfully!", cancelTitle: "Cancel", submitTitle: "Ok", alertimage: "recipes"){
self.detailContainerView.isHidden = false
}
self.present(alertVC,animated: true)
break
case .failure :
let alertVC = self.alertservices.alert(title: "Add Recipe : Basic Level", message: "Something went wrong. Please try again!", cancelTitle: "Cancel", submitTitle: "Ok", alertimage: "recipes"){
}
self.present(alertVC,animated: true)
break
}
})
If I use .responseData then I get the this output success(118 bytes) instead of what is mentioned below. But the actual response which I get when I place the values in the postman is
{
"response": "success",
"status": 0,
"recipe_id": 10422
}
If I use .responseJSON then the following error is shown at the console.
["recipe_preparation_time": "00:10:00", "recipe_title": "test recipe", "recipe_category": "2", "veg_status": "1", "recipe_food_type[]": [1, 3], "type": "3", "recipe_cooking_time": "00:10:00", "recipe_country": "", "customer_id": "5", "added_by": "5", "difficulty_level": "1"]
success({
error = {
"recipe_food_type" = (
"The recipe food type field is required."
);
};
message = "Validation Error";
status = 406;
})
Can anyone help me to solve this?
As #Frankenstein mentioned its good to create Codable struct. But when you are using Alamofire you can use:
AF.request(url).validate().responseDecodable(of: Response.self) { response in
// and then on response.value you have your response struct
}
Create a Codable resposne struct, and decode using JSONDecoder():
struct Response: Codable {
let response: String
let status, recipeId: Int
enum CodingKeys: String, CodingKey {
case response, status
case recipeId = "recipe_id"
}
}
Add this format for you request:
AF.request(url, method: .post, parameters: parameter, encoding: JSONEncoding.default).validate().responseDecodable(of: Response.self) { response in
Related
This is what i am trying to accomplish:
Use a barcode scanner to scan an item and send a "GET REQUEST" to retrieve json data.
Modify the data with user input (change number, text etc).
Use the modified data/variable to send out a "PUT REQUEST" as httpbody.
I dont know what the best way to accomplish this is, im so lost! Can i somehow return the variable "parameters" out of the function so that i can modify it and send it out with another function?
The below code is not the full code, i removed a big part to make it easier to read. It contains a "get" function, dont know where to go from here.
Thanks for checking it out, just looking for someone to point me in the right direction.
import UIKit
import AVFoundation
import QRCodeReader
import Alamofire
// MARK: - Main
struct Main: Codable {
let objects: [Object]
}
// MARK: - Object
struct Object: Codable {
let inventory: [Inventory]
}
// MARK: - Inventory
struct Inventory: Codable {
let coordinates: String
}
func test() {
// MARK: - LOGIN DETAILS
let headers: HTTPHeaders = [
.authorization(username: "username", password: "password"),
.accept("application/json")]
// MARK: - API REQUEST
AF.request("URL LINK", headers: headers).validate().responseJSON { response in
// MARK: - CHECK FOR ERRORS
if let error = response.error {
print(error)
// MARK: - ERROR MESSAGE
DispatchQueue.main.async
{ let alert = UIAlertController(title: "ERROR", message: "Something went wrong", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true)}
return}
// MARK: - PRINT RESPONSE
if response.response != nil
{print (response.response!) }
// MARK: - PRINT DATA
if response.data != nil
{ print(response.data!)
let decoder = JSONDecoder()
do
{
let api = try decoder.decode(Main.self, from: response.data!)
let parameters = [
"meta": [
"language": "en"
],
"request": [
"inventory": [
[
"id": 6534206,
"warehouseid": 1,
"instock": 3,
"threshold": 0,
"reserved": 0,
"coordinates": "\(api.objects[0].inventory[0].coordinates)",
"note": "",
"prodno": 25669,
"soldout": 0
]
]
]
]
}
catch {
print("Error in JSON parsing")
}
}
}
}
You can use the closure to return the value out of the function. This practice is functional programming, almost using for async function.
func test(completion: ([String: AnyObject]) -> ()) {
...
let param = [“meta”: [“language”: “en”],...]
completion(param)
}
And then, to use it:
test(completion: { param in
// handle the “param”
})
i am using this code to send an image and text to an api:
func uploadImageAndData(_ url:String,parameters1:Parameters,headers1:HTTPHeaders,images:[UIImage]){
Alamofire.upload(multipartFormData: { multipartFormData in
// import image to request
var i=0
for imageData in images {
// multipartFormData.append(self.resizeImage(image: uploadedProfileImage, targetSize: CGSize(width: 200, height: 200)
multipartFormData.append(imageData.pngData()!, withName: "profilePic", fileName: "profileimage"+".jpeg", mimeType: "image/jpeg")
i += 1
}
for (key, value) in parameters1 {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
} ,to: url,method:.post,
headers:[:],
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (Progress) in
print("showuing upload progress")
print("Upload Progress: \(Progress.fractionCompleted)")
//SwiftSpinner.show(progress: Progress.fractionCompleted*100, title: "تحميل")
})
upload.responseJSON { response in
print(response.response?.statusCode as Any)
if let data = response.result.value, let utf8Text = String(data: data as! Data, encoding: .utf8) {
print("New Func Data: \(utf8Text)")
}
switch response.response?.statusCode {
case 201 :
print("Success")
break
case 413 :
print("Post too large")
break
case 200 :
print("200")
break
case 400 :
print("400")
break
case 401 :
print("401")
break
case 302 :
print("302")
break
case 500 :
print("500")
break
default: break
}
}
return
case .failure(let encodingError): break
}
})
}
and i got these datas :
let address: Parameters = [
"location" : addressField.text!,
"locationLat" :pickedLocationLat,
"locationLong" :pickedLocationLong
]
let body: Parameters = [
"name": "Sample Name",
"email": "test#test.com",
"password": "test123",
"address": address
]
and i am accessing the function using this code
var head = [String:Any]()
head["Accept"]="application/json"
uploadImageAndData(BASE_URL", parameters1: body, headers1: head as! HTTPHeaders, images: [uploadedProfileImage])
this code is throwing an error like
Terminating app due to uncaught exception 'NSInvalidArgumentException'
reason: '-[_TtGCs26_SwiftDeferredNSDictionarySSP__$ dataUsingEncoding:]: unrecognized selector sent to instance 0x6000015bed00'
terminating with uncaught exception of type NSException
i dont know what is causing this problem the api requires a json body with a content-type of application/json
i tired removing all the content of the body parameter except for the name to try and send only the name and when i do that the image uploads successfully but it still gives me this error,so please help me figure out this problem.
You need to make values a string not double
let address: Parameters = [
"location" : addressField.text!,
"locationLat" :"\(pickedLocationLat)",
"locationLong" :"\(pickedLocationLong)"
]
I'm trying to fetch data from a GET request using Alamofire in Swift. There's an issue where it's not getting the full response from the request. The response is an array with nested arrays some String and some [String:Any]. I've none of the [String:Any] gets pulled in using Alamofire and think this is a serious bug. Postman shows the nested array values but not Alamofire.
The request
Alamofire.request(request.getFullUrl(param: paramsForUrl), method: request.getMethodType(), parameters: data, encoding: request.getEncoding(), headers: headers).validate(statusCode: 200..<500).responseJSON { response in }
What a typical response should look like
{
"uuid": "787FDS8-FS7FS7DG9-FSD789FCS98",
"name": "Show time",
"views_count": 0,
"comments_count": 0,
...
"events": [
{
"uuid": "f69a358e-9a1e-427c-a158-95dfc8c54ed7",
"name": "Test",
...
},
{
"uuid": "8993b639-f6c9-4d20-b8a9-c43c73a9828b",
"name": "Test 2",
...
},
...
]
"times: [
{
"name: "test time 1",
"clock: "Face"
},
{
"name": "test time 2",
"clock: "Back"
}
]
}
What's missing
Anything inside nested arrays: events, times. If I have a simple array of String then Alamofire gets these. It doesn't show anything nested and this is with both printing response.result.value and JSON decoding the response and accessing events directly. It doesn't see events or times.
Thanks for your help.
May be your JSON is not valid. To check that try changing responseJSON to responseString and see if it prints all the data e.g.
Alamofire.request(url ,method: .get ,parameters: data).validate().responseString{ response in
switch response.result{
case .success:
let s = response.result.value ?? "nil"
print("API Response: \(s)")
case .failure:
debugPrint(response)
}
}
If the above is printing all the data from your server than you need to fix the service
Delete .validate(statusCode: 200..<500) and try again.
Alamofire.request(url ,method: .get ,parameters: parameter).responseJSON{ response in
switch response.result{
case .success:
let value = response.result.value ?? "nil"
print("API Response: \(value)")
case .failure:
print("error")
}
}
I am trying to make a request with Alamofire and Swift 3.0 but it is always going to the failure status.
This is the code I have right now:
let str = "http://url/{\"user\":\"1\",\"pass\":\"1\"}"
let encodedUrl = str.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
Alamofire.request(encodedUrl!, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
switch(response.result) {
case .success(_):
print("Success")
break
case .failure(_):
print("Failure")
break
}
}
If I use the encodedUrl on Postman application I get the response well. It gives to me the following JSON:
[
{
"user": "1",
"name": "peter"
},
{
"user": "4",
"name": "andrew"
}]
What am I missing?
Thanks in advance!
Finally, it seems that I was retrieving an extra String out of the JSON because I used an echo on my API.
I could not see it because I had on Postman the option to show the response as JSON so the String was not being shown. I have changed it to HTML and then I was able to see the String.
Removing the extra String let me enter on the success status of Alamofire.
#IBAction func login(sender: UIButton) {
let parameters = [
"username": usernameTextField?.text,
"password": passwordTextField?.text
]
Alamofire.request(.POST, "http://192.168.1.107:8080/api/v1/user/login", parameters: parameters, encoding: .JSON)
.validate()
.responseJSON { response in
switch response.result {
case .Success(let JSON):
print("Validation Successful")
if (JSON["status"] as! String != "Success") {
self.popup("Invalid Account", message: "Please check your username and password and try again")
}
case .Failure(let error):
print(error)
}
}
}
The parameters worked fine when I have the username and password hardcoded inside the dictionary. But when I changed it to a textfield, Im getting the error that says Cannot convert value of type [String: String?] to [String: Anyobject]?
How can I make the parameters anyobject so it would be accepted?
The error message is showing the there is optional type in params.
just unwrap the values before using it if you are creating textfield at run time.
if not creating at runtime simply use it like
let parameters = [
"username": usernameTextField.text,
"password": passwordTextField.text
]