How to send array parameter in alamofire multipartform? - swift

I have an array, several parameters
var arr: [String] = [ "a", "b", "c", "d", "e"]
...
let parameters: [String: Any] = [
"myArray" : self.arr,
"text" : self.text
...
]
I want to upload
AF.upload(mutlipartFormData: { multipart in
for (key, value) in parameters {
if key == "myArray" {
// This code is problem
for idx in value as! [String] {
multipartFormData.append("\(idx)".data(using: .utf8, allowLossyConversion: false)!, withName: "\(key)")
}
}
}
I tried that code, It uploaded just 1 element in arr. I want to send the array

you just need to convert your array in JSON String.
var arr: [String] = [ "a", "b", "c", "d", "e"]
var strArr = ""
if let theJSONData = try? JSONSerialization.data(
withJSONObject: arr,
options: []) {
let theJSONText = String(data: theJSONData,
encoding: .ascii)
strArr = theJSONText ?? ""
print("JSON string = \(theJSONText!)")
}
let param: [String: Any] = [
"myArray" : strArr,
"text" : "text"
]
print(param)
Alamofire.upload(multipartFormData: {
multipartFormData in
for (key, value) in param {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, to: "apiurl", method: .post, encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON {
response in
print(response.result)
}
case .failure(let encodingError):
break
}
})

-->you can create a function for uploading form data like this
func makeFormDataAPICallDecodable<T: Codable>(url: String, params: [String: Any], objectType: T.Type,
success: #escaping(_ responseObject: T) -> Void,
failure: #escaping (_ error: String) -> Void) {
// Almofire upload request
AF.upload(multipartFormData: { multiPartData in
for (key, value) in params {
if value is UIImage {
let img = (value as? UIImage)?.jpegData(compressionQuality: 0.5)
multiPartData.append(img!, withName: key, fileName: "img_\(name).jpeg", mimeType: "image/jpeg")
} else if value is NSArray {
for childValue in value as? NSArray ?? [] {
if childValue is UIImage {
let img = (childValue as? UIImage)?.jpegData(compressionQuality: 0.5)
multiPartData.append(img!, withName: key, fileName: "profile_image.png", mimeType: "image/jpeg")
}
}
} else if value is NSURL || value is URL {
do {
guard let pdf: URL = value as? URL else { return }
let name = pdf.lastPathComponent
let mimeType = pdf.mimeType()
let pdfData = try Data(contentsOf: pdf)
multiPartData.append(pdfData, withName: key, fileName: name, mimeType: mimeType)
} catch { print(error) }
} else {
if value is String || value is Int || value is Bool {
multiPartData.append("\(value)".data(using: .utf8)!, withName: key)
}
}
}
}, to: urlIs,method: .post, headers: headers).responseDecodable(of: FetchAPI<T>.self) { response in
// preetify data
if let data = response.data {
let str = data.prettyPrintedJSONString!
Logger.logResponse(ofAPI: "\(urlIs)", logType: .success, object: str)
}
// response result
switch response.result {
case .success(let data):
// check auth token Exp condition
if data.statusCode == 401 {
self.navigateToLogin()
return
}
// check flag status
if data.flag! { success(data.data!) } else { failure(data.message!) }
case .failure(let error):
failure("Something went wrong.")
Logger.log(logType: .error, object: error.localizedDescription)
}
}
} else { failure(ServerAPI.errorMessages.kNoInternetConnectionMessage) }
}
-> You can use it like
let params: [String : Any] = [User.CodingKeys.userName.rawValue: data.name!,
User.CodingKeys.email.rawValue: data.email!,
User.CodingKeys.userRole.rawValue: data.userRole!,
User.CodingKeys.phoneNumber.rawValue: data.phoneNumber!,
kPassword: data.password!,
User.CodingKeys.employeeID.rawValue: data.employeeId!,
User.CodingKeys.departmentID.rawValue: data.department!,
kDeviceType:1] // ["Key": value]
makeAPICallDecodable(url: ServerAPI.register, params: params, objectType: User.self, success: {
response in
print(response)
}, failure: { error in
print(error)
})
-> parameter objectData is the object in which you want response is an generic <T.type>

Related

Swift form-data using Alamofire 5 with parameters

I am beginner iOS developer and I don't know how to upload a file using Alamofire 5, I know there are a lot of similar questions, but all the topics here are from very old versions and I couldn't get it working. I tried this code, but I couldn't fit to my case, it gives me success, but file is not uploaded and the result I get is not what I get in postman. This is the code:
func uploadFile(_ parameters: Parameters) {
AF.upload(multipartFormData: { multipartFormData in
URLEncoding.default.queryParameters(parameters).forEach { (key, value) in
if let data = value.data(using: .utf8) {
multipartFormData.append(data, withName: key)
}
}
}, to: url)
.responseDecodable(of: FileCreation.self) { response in
switch response.result {
case .success(let data):
print(data, "success")
case .failure(let error):
print(error)
}
}
}
usage:
#IBAction func upload(_ sender: UIButton) {
guard let data = image?.jpegData(compressionQuality: 0.5)! else { return }
let parameters = ["addFiles": data]
uploadFile(parameters)
}
Here's Xcode output:
Here you can see postman response after I upload file:
Alamofire.upload(multipartFormData: {
multipartFormData in
if let imageData = image[0].jpegData(compressionQuality: 0.6) {
multipartFormData.append(imageData, withName: "addFiles", fileName: "file.pdf", mimeType: "application/pdf")
}
for (key, value) in param {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
},to: apiurl, method: .post, headers: headers, encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON {
response in
print(response.result)
}
//break
case .failure(let encodingError):
break
}
})
Try This
func uploadFilesToServer(_ url: String, method: HTTPMethod, parameters: [String:Any]?, file: [String:Any]?, fileType: String, fileName: String, headers:HTTPHeaders?, completionHandler: #escaping (_ result: Data?, _ success: Bool, _ status: String) -> ()) {
var status = Bool()
var message = String()
let url = URL(string: url)
AF.upload(multipartFormData: { multiPart in
if let files = file {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy-hh-mm-ss"
let dateString = dateFormatter.string(from: Date())
for (key, value) in files {
if fileType == "pdf" {
let filePath = URL(fileURLWithPath: value as! String)
multiPart.append(filePath, withName: "\(key)", fileName: fileName, mimeType: "file/pdf")
} else {
multiPart.append(value as! Data, withName: "\(key)", fileName: "Uploads\(dateString).png", mimeType: "image/png")
}
}
}
if let params = parameters {
for (key, value) in params {
multiPart.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}
}, to: url!, method: method, headers: headers ?? nil)
.validate()
.uploadProgress(closure: { progress in
print(progress)
})
.responseJSON { response in
switch response.result {
case .success(let responseData):
print(responseData)
case .failure(let networkErr):
switch networkErr {
case .responseSerializationFailed(reason: _):
message = "Something went wrong"
case .sessionTaskFailed(error: let err):
message = err.localizedDescription
default:
message = "Something went wrong"
}
completionHandler(nil, false, message)
break
}
}
}
usage
uploadFilesToServer(url, method: .post, parameters: params, file: uploadFile, fileType: "pdf", fileName: fileNme, headers: tokenHeader) { [self] responseData, isSuccess, responseMsg in
if isSuccess {
} else {
}
}

Swift: getting nil when decoding API response

I'm having an issue decoding an API response.
So we have a NetworkManager class which we use to decode APIs. I have a simple GET endpoint that I need to retrieve a list of airports from. Here is the endpoint:
static let airports = Endpoint(url: "/test/airports")
Endpoint is defined as follows:
public struct Endpoint : Equatable {
public init(url: String? = nil, pattern: String? = nil, methods: [Test.HTTPMethod] = [.get], type: Test.EncodingType = .json)
}
Then in our network manager we have:
public func call<R: Decodable>(_ endpoint: Endpoint,
with args: [String: String]? = nil,
using method: HTTPMethod = .get,
expecting response: R.Type?,
completion: APIResponse<R>) {
call(endpoint, with: args, parameters: Nothing(),
using: method, posting: Nothing(), expecting: response, completion: completion)
}
My Airport model is as follows:
struct Airport: Codable {
let id: String
let name: String
let iata3: String
let icao4: String
let countryCode: String
}
And then I'm calling the endpoint like:
private func getAirportsList() {
API.client.call(.airports, expecting: [Airport].self) { (result, airports) in
print(airports)
}
}
Now I'm using Charles to proxy and I am getting the response I expect:
[{
"id": "5f92b0269c983567fc4b9683",
"name": "Amsterdam Schiphol",
"iata3": "AMS",
"icao4": "EHAM",
"countryCode": "NL"
}, {
"id": "5f92b0269c983567fc4b9685",
"name": "Bahrain International",
"iata3": "BAH",
"icao4": "OBBI",
"countryCode": "BH"
}, {
"id": "5f92b0269c983567fc4b968b",
"name": "Bankstown",
"iata3": "BWU",
"icao4": "YSBK",
"countryCode": "AU"
}]
But in my getAirports() method, airports is nil. I'm really struggling to see why. Clearly the endpoint is being hit correctly but my decoding is failing.
Edit:
Full method:
private func call<P: Encodable, B: Encodable, R: Decodable>(_ endpoint: Endpoint,
with args: [String: String]? = nil,
parameters params: P?,
using method: HTTPMethod = .get,
posting body: B?,
expecting responseType: R.Type?,
completion: APIResponse<R>) {
// Prepare our URL components
guard var urlComponents = URLComponents(string: baseURL.absoluteString) else {
completion?(.failure(nil, NetworkError(reason: .invalidURL)), nil)
return
}
guard let endpointPath = endpoint.url(with: args) else {
completion?(.failure(nil, NetworkError(reason: .invalidURL)), nil)
return
}
urlComponents.path = urlComponents.path.appending(endpointPath)
// Apply our parameters
applyParameters: if let parameters = try? params.asDictionary() {
if parameters.count == 0 {
break applyParameters
}
var queryItems = [URLQueryItem]()
for (key, value) in parameters {
if let value = value as? String {
let queryItem = URLQueryItem(name: key, value: value)
queryItems.append(queryItem)
}
}
urlComponents.queryItems = queryItems
}
// Try to build the URL, bad request if we can't
guard let urlString = urlComponents.url?.absoluteString.removingPercentEncoding,
var url = URL(string: urlString) else {
completion?(.failure(nil, NetworkError(reason: .invalidURL)), nil)
return
}
if let uuid = UIDevice.current.identifierForVendor?.uuidString, endpoint.pattern == "/logging/v1/device/<device_id>" {
let us = "http://192.168.6.128:3000/logging/v1/device/\(uuid)"
guard let u = URL(string: us) else { return }
url = u
}
// Can we call this method on this endpoint? If not, lets not try to continue
guard endpoint.httpMethods.contains(method) else {
completion?(.failure(nil, NetworkError(reason: .methodNotAllowed)), nil)
return
}
// Apply debug cookie
if let debugCookie = debugCookie {
HTTPCookieStorage.shared.setCookies(
HTTPCookie.cookies(
withResponseHeaderFields: ["Set-Cookie": debugCookie],
for:url
), for: url, mainDocumentURL: url)
}
// Build our request
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
if let headers = headers {
for (key, value) in headers {
request.setValue(value, forHTTPHeaderField: key)
}
}
// If we are posting, safely retrieve the body and try to assign it to our request
if !(body is NothingProtocol) {
guard let body = body else {
completion?(.failure(nil, NetworkError(reason: .buildingPayload)), nil)
return
}
do {
let result = try encode(body: body, type: endpoint.encodingType)
request.httpBody = result.data
request.setValue(result.headerValue, forHTTPHeaderField: "Content-Type")
} catch {
completion?(.failure(nil, NetworkError(reason: .buildingPayload)), nil)
return
}
}
// Build our response handler
let task = session.dataTask(with: request as URLRequest) { (rawData, response, error) in
// Print some logs to help track requests
var debugOutput = "URL\n\(url)\n\n"
if !(params is Nothing.Type) {
debugOutput.append(contentsOf: "PARAMETERS\n\(params.asJSONString() ?? "No Parameters")\n\n")
}
if !(body is Nothing.Type) {
debugOutput.append(contentsOf: "BODY\n\(body.asJSONString() ?? "No Body")\n\n")
}
if let responseData = rawData {
debugOutput.append(contentsOf: "RESPONSE\n\(String(data: responseData, encoding: .utf8) ?? "No Response Content")")
}
Logging.client.record(debugOutput, domain: .network, level: .debug)
guard let httpResponse = response as? HTTPURLResponse else {
guard error == nil else {
completion?(.failure(nil, NetworkError(reason: .unwrappingResponse)), nil)
return
}
completion?(.failure(nil, NetworkError(reason: .invalidResponseType)), nil)
return
}
let statusCode = httpResponse.statusCode
// We have an error, return it
guard error == nil, NetworkManager.successStatusRange.contains(statusCode) else {
var output: Any?
if let data = rawData {
output = (try? JSONSerialization.jsonObject(with: data,
options: .allowFragments)) ?? "Unable to connect"
Logging.client.record("Response: \(String(data: data, encoding: .utf8) ?? "No error data")", domain: .network)
}
completion?(.failure(statusCode, NetworkError(reason: .requestFailed, json: output)), nil)
return
}
// Safely cast the responseType we are expecting
guard let responseType = responseType else {
completion?(.failure(statusCode, NetworkError(reason: .castingToExpectedType)), nil)
return
}
// If we are expecting nothing, return now (since we will have nothing!)
if responseType is Nothing.Type {
completion?(.success(statusCode), nil)
return
}
guard let data = rawData else {
assertionFailure("Could not cast data from payload when we passed pre-cast checks")
return
}
// Decode the JSON and cast to our expected response type
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let responseObject = try decoder.decode(responseType, from: data)
completion?(.success(statusCode), responseObject)
return
} catch let error {
let content = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
Logging.client.record("Failed to build codable from JSON: \(String(describing: content))\n\nError: \(error)", domain: .network, level: .error)
assertionFailure("Failed to build codable from JSON: \(error)")
completion?(.failure(statusCode, NetworkError(reason: .castingToExpectedType)), nil)
return
}
}
// Submit our request
task.resume()
}

How to work with Multipart using Alamofire in Swift with multiple images with different keys and parameters with multiple kinds

How to handle multipart in swift if you are dealing with multiple images having different keys and also having parameter dictionary with different kinds of key:value pairs like "String":"Any", "String":"[Any]", [[String:Any]].
let headers: HTTPHeaders = ["Content-type": "multipart/form-data"]
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
//Todo: - Images
var c = 0
for dictImage in arrImage {
let validDict = kSharedInstance.getDictionary(dictImage)
for keyName in validDict.keys {
print(keyName)
//Incr
c += 1
if let imageData = validDict[keyName] as? Data {
multipartFormData.append(imageData, withName: "\(keyName)", fileName: "\(Date().timeIntervalSince1970).jpeg", mimeType: "image/jpeg")
}
}
}
}, usingThreshold: UInt64(), to: urlString, method: .post, headers: headers) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
print("Succesfully uploaded")
if((response.result.value) != nil) {
debugPrint(response.result.value!)
let jsonData = JSON(response.result.value!)
if jsonData["status"].bool == true {
completion(jsonData.dictionaryObject!, true)
}else
{
completion(jsonData.dictionaryObject!, false)
}
}
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
failure(error, false)
}
}
Please check below code. Hope it helps you
Alamofire.upload(
multipartFormData: { MultipartFormData in
for (key, value) in parameters {
MultipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
}
for i in 0 ..< files.count {
let fileName : String = "image\(i).jpg"
let datum : Data = files[i]
MultipartFormData.append(datum, withName: fileParamName, fileName: fileName, mimeType: "image/jpg")
}
}, to: URLString, method: .post, headers: headers) { (result) in
switch(result) {
case .success(let upload, _, _):
upload.responseJSON { response in
}
break;
case .failure(_):
}
}

How to get JSON response and parse through it [duplicate]

Following code I have written and I am getting response in JSON also but the type of JSON is "AnyObject" and I am not able to convert that into Array so that I can use that.
Alamofire.request(.POST, "MY URL", parameters:parameters, encoding: .JSON) .responseJSON
{
(request, response, JSON, error) in
println(JSON?)
}
The answer for Swift 2.0 Alamofire 3.0 should actually look more like this:
Alamofire.request(.POST, url, parameters: parameters, encoding:.JSON).responseJSON
{ response in switch response.result {
case .Success(let JSON):
print("Success with JSON: \(JSON)")
let response = JSON as! NSDictionary
//example if there is an id
let userId = response.objectForKey("id")!
case .Failure(let error):
print("Request failed with error: \(error)")
}
}
https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md
UPDATE for Alamofire 4.0 and Swift 3.0 :
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
print(response)
//to get status code
if let status = response.response?.statusCode {
switch(status){
case 201:
print("example success")
default:
print("error with response status: \(status)")
}
}
//to get JSON return value
if let result = response.result.value {
let JSON = result as! NSDictionary
print(JSON)
}
}
like above mention you can use SwiftyJSON library and get your values like i have done below
Alamofire.request(.POST, "MY URL", parameters:parameters, encoding: .JSON) .responseJSON
{
(request, response, data, error) in
var json = JSON(data: data!)
println(json)
println(json["productList"][1])
}
my json product list return from script
{ "productList" :[
{"productName" : "PIZZA","id" : "1","productRate" : "120.00","productDescription" : "PIZZA AT 120Rs","productImage" : "uploads\/pizza.jpeg"},
{"productName" : "BURGER","id" : "2","productRate" : "100.00","productDescription" : "BURGER AT Rs 100","productImage" : "uploads/Burgers.jpg"}
]
}
output :
{
"productName" : "BURGER",
"id" : "2",
"productRate" : "100.00",
"productDescription" : "BURGER AT Rs 100",
"productImage" : "uploads/Burgers.jpg"
}
Swift 3, Alamofire 4.4, and SwiftyJSON:
Alamofire.request(url, method: .get)
.responseJSON { response in
if response.data != nil {
let json = JSON(data: response.data!)
let name = json["people"][0]["name"].string
if name != nil {
print(name!)
}
}
}
That will parse this JSON input:
{
people: [
{ name: 'John' },
{ name: 'Dave' }
]
}
I found the answer on GitHub for Swift2
https://github.com/Alamofire/Alamofire/issues/641
Alamofire.request(.GET, URLString, parameters: ["foo": "bar"])
.responseJSON { request, response, result in
switch result {
case .Success(let JSON):
print("Success with JSON: \(JSON)")
case .Failure(let data, let error):
print("Request failed with error: \(error)")
if let data = data {
print("Response data: \(NSString(data: data, encoding: NSUTF8StringEncoding)!)")
}
}
}
I'm neither a JSON expert nor a Swift expert, but the following is working for me. :) I have extracted the code from my current app, and only changed "MyLog to println", and indented with spaces to get it to show as a code block (hopefully I didn't break it).
func getServerCourseVersion(){
Alamofire.request(.GET,"\(PUBLIC_URL)/vtcver.php")
.responseJSON { (_,_, JSON, _) in
if let jsonResult = JSON as? Array<Dictionary<String,String>> {
let courseName = jsonResult[0]["courseName"]
let courseVersion = jsonResult[0]["courseVersion"]
let courseZipFile = jsonResult[0]["courseZipFile"]
println("JSON: courseName: \(courseName)")
println("JSON: courseVersion: \(courseVersion)")
println("JSON: courseZipFile: \(courseZipFile)")
}
}
}
Hope this helps.
Edit:
For reference, here is what my PHP Script returns:
[{"courseName": "Training Title","courseVersion": "1.01","courseZipFile": "101/files.zip"}]
Swift 5
class User: Decodable {
var name: String
var email: String
var token: String
enum CodingKeys: String, CodingKey {
case name
case email
case token
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
self.email = try container.decode(String.self, forKey: .email)
self.token = try container.decode(String.self, forKey: .token)
}
}
Alamofire API
Alamofire.request("url.endpoint/path", method: .get, parameters: params, encoding: URLEncoding.queryString, headers: nil)
.validate()
.responseJSON { response in
switch (response.result) {
case .success( _):
do {
let users = try JSONDecoder().decode([User].self, from: response.data!)
print(users)
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}
case .failure(let error):
print("Request error: \(error.localizedDescription)")
}
swift 3
pod 'Alamofire', '~> 4.4'
pod 'SwiftyJSON'
File json format:
{
"codeAd": {
"dateExpire": "2017/12/11",
"codeRemoveAd":"1231243134"
}
}
import Alamofire
import SwiftyJSON
private func downloadJson() {
Alamofire.request("https://yourlinkdownloadjson/abc").responseJSON { response in
debugPrint(response)
if let json = response.data {
let data = JSON(data: json)
print("data\(data["codeAd"]["dateExpire"])")
print("data\(data["codeAd"]["codeRemoveAd"])")
}
}
}
This was build with Xcode 10.1 and Swift 4
Perfect combination "Alamofire"(4.8.1) and "SwiftyJSON"(4.2.0). First you should install both pods
pod 'Alamofire' and pod 'SwiftyJSON'
The server response in JSON format:
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip;q=1.0, compress;q=0.5",
"Accept-Language": "en;q=1.0",
"Host": "httpbin.org",
"User-Agent": "AlamoFire TEST/1.0 (com.ighost.AlamoFire-TEST; build:1; iOS 12.1.0) Alamofire/4.8.1"
},
"origin": "200.55.140.181, 200.55.140.181",
"url": "https://httpbin.org/get"
}
In this case I want print the "Host" info : "Host": "httpbin.org"
Alamofire.request("https://httpbin.org/get").validate().responseJSON { response in
switch response.result {
case .success:
print("Validation Successful)")
if let json = response.data {
do{
let data = try JSON(data: json)
let str = data["headers"]["Host"]
print("DATA PARSED: \(str)")
}
catch{
print("JSON Error")
}
}
case .failure(let error):
print(error)
}
}
Keep Calm and happy Code😎
I found a way to convert the response.result.value (inside an Alamofire responseJSON closure) into JSON format that I use in my app.
I'm using Alamofire 3 and Swift 2.2.
Here's the code I used:
Alamofire.request(.POST, requestString,
parameters: parameters,
encoding: .JSON,
headers: headers).validate(statusCode: 200..<303)
.validate(contentType: ["application/json"])
.responseJSON { (response) in
NSLog("response = \(response)")
switch response.result {
case .Success:
guard let resultValue = response.result.value else {
NSLog("Result value in response is nil")
completionHandler(response: nil)
return
}
let responseJSON = JSON(resultValue)
// I do any processing this function needs to do with the JSON here
// Here I call a completionHandler I wrote for the success case
break
case .Failure(let error):
NSLog("Error result: \(error)")
// Here I call a completionHandler I wrote for the failure case
return
}
I usually use Gloss library to serialize or deserialize JSON in iOS. For example, I have JSON that looks like this:
{"ABDC":[{"AB":"qwerty","CD":"uiop"}],[{"AB":"12334","CD":"asdf"}]}
First, I model the JSON array in Gloss struct:
Struct Struct_Name: Decodable {
let IJ: String?
let KL: String?
init?(json: JSON){
self.IJ = "AB" <~~ json
self.KL = "CD" <~~ json
}
}
And then in Alamofire responseJSON, I do this following thing:
Alamofire.request(url, method: .get, paramters: parametersURL).validate(contentType: ["application/json"]).responseJSON{ response in
switch response.result{
case .success (let data):
guard let value = data as? JSON,
let eventsArrayJSON = value["ABDC"] as? [JSON]
else { fatalError() }
let struct_name = [Struct_Name].from(jsonArray: eventsArrayJSON)//the JSON deserialization is done here, after this line you can do anything with your JSON
for i in 0 ..< Int((struct_name?.count)!) {
print((struct_name?[i].IJ!)!)
print((struct_name?[i].KL!)!)
}
break
case .failure(let error):
print("Error: \(error)")
break
}
}
The output from the code above:
qwerty
uiop
1234
asdf
in swift 5 we do like, Use typealias for the completion. Typlealias nothing just use to clean the code.
typealias response = (Bool,Any?)->()
static func postCall(_ url : String, param : [String : Any],completion : #escaping response){
Alamofire.request(url, method: .post, parameters: param, encoding: JSONEncoding.default, headers: [:]).responseJSON { (response) in
switch response.result {
case .success(let JSON):
print("\n\n Success value and JSON: \(JSON)")
case .failure(let error):
print("\n\n Request failed with error: \(error)")
}
}
}
The easy answer is to let AlamoFire do the decoding directly.
Surprisingly, you don't use the .responseJSON because that returns an untyped json object
Instead, you make your objects Decodable - and ask AF to decode directly to them
My json response contains an array of Account objects. I only care about the id and name keys (though there are many more)
struct Account:Codable {
let id:Int
let name:String
}
then simply
AF.request(url,
method: .get)
.responseDecodable(of:[Account].self) { response in
switch response.result {
case .success:
switch response.response?.statusCode {
case 200:
//response.value is of type [Account]
default:
//handle other cases
}
case let .failure(error):
//probably the decoding failed because your json doesn't match the expected format
}
}
let semaphore = DispatchSemaphore (value: 0)
var request = URLRequest(url: URL(string: Constant.localBaseurl2 + "compID")!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let response = response {
let nsHTTPResponse = response as! HTTPURLResponse
print(nsHTTPResponse)
}
if let error = error {
print ("\(error)")
return
}
if let data = data {
DispatchQueue.main.async {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase//or any other Decoder\
do{
let jsonDecoder = JSONDecoder()
let memberRecord = try jsonDecoder.decode(COMPLAINTSVC.GetComplaints.self, from: data)
print(memberRecord.message)
for detailData in memberRecord.message{
print(detailData)
}
}catch{
print(error.localizedDescription)
}
}
}
semaphore.signal()
}
task.resume()
semaphore.wait()
}
pod 'Alamofire'
pod 'SwiftyJSON'
pod 'ReachabilitySwift'
import UIKit
import Alamofire
import SwiftyJSON
import SystemConfiguration
class WebServiceHelper: NSObject {
typealias SuccessHandler = (JSON) -> Void
typealias FailureHandler = (Error) -> Void
// MARK: - Internet Connectivity
class func isConnectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return false
}
var flags: SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
return false
}
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
}
// MARK: - Helper Methods
class func getWebServiceCall(_ strURL : String, isShowLoader : Bool, success : #escaping SuccessHandler, failure : #escaping FailureHandler)
{
if isConnectedToNetwork() {
print(strURL)
if isShowLoader == true {
AppDelegate.getDelegate().showLoader()
}
Alamofire.request(strURL).responseJSON { (resObj) -> Void in
print(resObj)
if resObj.result.isSuccess {
let resJson = JSON(resObj.result.value!)
if isShowLoader == true {
AppDelegate.getDelegate().dismissLoader()
}
debugPrint(resJson)
success(resJson)
}
if resObj.result.isFailure {
let error : Error = resObj.result.error!
if isShowLoader == true {
AppDelegate.getDelegate().dismissLoader()
}
debugPrint(error)
failure(error)
}
}
}else {
CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
}
}
class func getWebServiceCall(_ strURL : String, params : [String : AnyObject]?, isShowLoader : Bool, success : #escaping SuccessHandler, failure :#escaping FailureHandler){
if isConnectedToNetwork() {
if isShowLoader == true {
AppDelegate.getDelegate().showLoader()
}
Alamofire.request(strURL, method: .get, parameters: params, encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: {(resObj) -> Void in
print(resObj)
if resObj.result.isSuccess {
let resJson = JSON(resObj.result.value!)
if isShowLoader == true {
AppDelegate.getDelegate().dismissLoader()
}
success(resJson)
}
if resObj.result.isFailure {
let error : Error = resObj.result.error!
if isShowLoader == true {
AppDelegate.getDelegate().dismissLoader()
}
failure(error)
}
})
}
else {
CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
}
}
class func postWebServiceCall(_ strURL : String, params : [String : AnyObject]?, isShowLoader : Bool, success : #escaping SuccessHandler, failure :#escaping FailureHandler)
{
if isConnectedToNetwork()
{
if isShowLoader == true
{
AppDelegate.getDelegate().showLoader()
}
Alamofire.request(strURL, method: .post, parameters: params, encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: {(resObj) -> Void in
print(resObj)
if resObj.result.isSuccess
{
let resJson = JSON(resObj.result.value!)
if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}
success(resJson)
}
if resObj.result.isFailure
{
let error : Error = resObj.result.error!
if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}
failure(error)
}
})
}else {
CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
}
}
class func postWebServiceCallWithImage(_ strURL : String, image : UIImage!, strImageParam : String, params : [String : AnyObject]?, isShowLoader : Bool, success : #escaping SuccessHandler, failure : #escaping FailureHandler)
{
if isConnectedToNetwork() {
if isShowLoader == true
{
AppDelegate.getDelegate().showLoader()
}
Alamofire.upload(
multipartFormData: { multipartFormData in
if let imageData = UIImageJPEGRepresentation(image, 0.5) {
multipartFormData.append(imageData, withName: "Image.jpg")
}
for (key, value) in params! {
let data = value as! String
multipartFormData.append(data.data(using: String.Encoding.utf8)!, withName: key)
print(multipartFormData)
}
},
to: strURL,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
//let datastring = String(data: response, encoding: String.Encoding.utf8)
// print(datastring)
}
case .failure(let encodingError):
print(encodingError)
if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}
let error : NSError = encodingError as NSError
failure(error)
}
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { (response) -> Void in
if response.result.isSuccess
{
let resJson = JSON(response.result.value!)
if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}
success(resJson)
}
if response.result.isFailure
{
let error : Error = response.result.error! as Error
if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}
failure(error)
}
}
case .failure(let encodingError):
if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}
let error : NSError = encodingError as NSError
failure(error)
}
}
)
}
else
{
CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
}
}
}
==================================
Call Method
let aParams : [String : String] = [
"ReqCode" : Constants.kRequestCodeLogin,
]
WebServiceHelper.postWebServiceCall(Constants.BaseURL, params: aParams as [String : AnyObject]?, isShowLoader: true, success: { (responceObj) in
if "\(responceObj["RespCode"])" != "1"
{
let alert = UIAlertController(title: Constants.kAppName, message: "\(responceObj["RespMsg"])", preferredStyle: UIAlertControllerStyle.alert)
let OKAction = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction!) in
}
alert.addAction(OKAction)
self.present(alert, animated: true, completion: nil)
}
else
{
let aParams : [String : String] = [
"Password" : self.dictAddLogin[AddLoginConstants.kPassword]!,
]
CommonMethods.saveCustomObject(aParams as AnyObject?, key: Constants.kLoginData)
}
}, failure:
{ (error) in
CommonMethods.showAlertWithError(Constants.kALERT_TITLE_Error, strMessage: error.localizedDescription,withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
})
}

Alamofire error copying matching creds - Swift

we are working to get an upload to an API with a POST method. We are trying to push an image. We are getting the next error
success(request: 2018-02-03 16:27:53.087629-0800 Optimio-iOS[5425:201118] CredStore - performQuery - Error copying matching creds. Error=-25300, query={
class = inet;
"m_Limit" = "m_LimitAll";
ptcl = htps;
"r_Attributes" = 1;
sdmn = "llegoelbigotes.ubiqme.es";
srvr = "llegoelbigotes.ubiqme.es";
sync = syna;
}
$ curl -v \
-X POST \
-H "Content-Type: multipart/form-data; boundary=alamofire.boundary.7105b62be90b880b" \
-H "Accept-Language: en;q=1.0, es-ES;q=0.9" \
-H "Authorization: Token 1b0ad885a95334154ca3bfa79b3f52ca35c25e0e" \
-H "User-Agent: Optimio-iOS/1.0 (Ubiqme-com.ubiqme.ubiqme; build:1; iOS 11.2.0) Alamofire/4.6.0" \
-H "Accept-Encoding: gzip;q=1.0, compress;q=0.5" \
"https://llegoelbigotes.ubiqme.es/api/new-ticket", streamingFromDisk: true, streamFileURL: Optional(file:///Users/polvallsortiz/Library/Developer/CoreSimulator/Devices/EE663E81-6611-4B69-ABD6-AF97D19D6FB7/data/Containers/Data/Application/E7B9F357-DD51-4512-8173-37C932C0E4B9/tmp/org.alamofire.manager/multipart.form.data/74C9B75E-614D-4FCD-9DBC-1F5D07D773C4))
Our code is the next one:
func myImageUploadRequest() {
guard let urlStr = "https://llegoelbigotes.ubiqme.es/api/new-ticket".addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed),
let url = URL(string: urlStr)
else {return}
let isPaymentCard = card ? "true" : "false"
let headers: HTTPHeaders = ["Authorization": "Token \(token!)"]
let param = [ "comment": comment, "category": String(category), "amount": String(money), "payment_card": isPaymentCard ]
Alamofire.upload(multipartFormData: { multipartFormData in
if let imageData = UIImageJPEGRepresentation(self.image,0.5)
{ multipartFormData.append(imageData,withName:"image",fileName:"image.jpeg",mimeType:"image/jpeg") }
for(key,value) in param {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
}, usingThreshold: UInt64.init(),
to: urlStr,
method: .post,
headers: headers) {(result) in
print(result)
switch result{
case .success(let upload, _, _):
upload.responseJSON {
response in
print("Succesfully uploaded")
if let err = response.error{
print(err)
return
}
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
print(error)
}
}
}
Anyone can show us some tips or say what might be wrong?
Thanks to all the community!
-> I have created a dynamic function for uploading Image and Files you can even upload multiple images and files my this
func makeFormDataAPICall<T: Codable>(url: String, params: [String: Any], objectType: T.Type,
success: #escaping(_ responseObject: T) -> Void,
failure: #escaping (_ error: String) -> Void) {
let name = self.randomNumberWith(digits: 6)
self.headers = [kAuthorization: self.userData?.authToken ?? ""]
//Network check
if Utilities.isConnectedToNetwork() {
guard let urlIs = URL(string: url) else {
failure(ServerAPI.errorMessages.kServerDownError)
return
}
// Almofire upload request
AF.upload(multipartFormData: { multiPartData in
for (key, value) in params {
if value is UIImage {
let img = (value as? UIImage)?.jpegData(compressionQuality: 0.5)
multiPartData.append(img!, withName: key, fileName: "img_\(name).jpeg", mimeType: "image/jpeg")
} else if value is NSArray {
for childValue in value as? NSArray ?? [] {
if childValue is UIImage {
let img = (childValue as? UIImage)?.jpegData(compressionQuality: 0.5)
multiPartData.append(img!, withName: key, fileName: "profile_image.png", mimeType: "image/jpeg")
}
}
} else if value is NSURL || value is URL {
do {
guard let pdf: URL = value as? URL else { return }
let name = pdf.lastPathComponent
let mimeType = pdf.mimeType()
let pdfData = try Data(contentsOf: pdf)
multiPartData.append(pdfData, withName: key, fileName: name, mimeType: mimeType)
} catch { print(error) }
} else {
if value is String || value is Int || value is Bool {
multiPartData.append("\(value)".data(using: .utf8)!, withName: key)
}
}
}
}, to: urlIs,method: .post, headers: headers).responseDecodable(of: FetchAPI<T>.self) { response in
// preetify data
if let data = response.data {
let str = data.prettyPrintedJSONString!
Logger.logResponse(ofAPI: "\(urlIs)", logType: .success, object: str)
}
// response result
switch response.result {
case .success(let data):
// check auth token Exp condition
if data.statusCode == 401 {
let appDelegate = AppDelegate.shared()
let rootVC = R.storyboard.auth.authNavigationController()!
appDelegate.window?.rootViewController = rootVC
return
}
// check flag status
if data.flag! { success(data.data!) } else { failure(data.message!) }
case .failure(let error):
failure("Something went wrong.")
Logger.log(logType: .error, object: error.localizedDescription)
}
}
} else { failure(ServerAPI.errorMessages.kNoInternetConnectionMessage) }
}
-> Usage
APIManager.shared.makeFormDataAPICall(url: ServerAPI.editProfile, params: params, objectType: User.self, success: { response in
success(response)
print(response)
}, failure: { error in
failure(error)
}) // 1st Parameter is URL 2nd Parameter are params to send
//3rd parameter is Object to which you want to convert the Json data into
//4th and 5th parameter are compilation handler which gives you response and errors accordingly
-> you can remove auth token conditions which I have written for myself
-> if you are passing data in json you just have to write JSONEncoding: JSONEncoding.default before "header parameter" in almofire function