POST request with string parameters and array - arrays

I want to make a POST request and pass some parameters.
The parameters I want to pass is:
- Item : String
- Length : String
- Names : String Array
- Age : String
Today I´m doing this
var URL: NSURL = NSURL(string: "URL")!
var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
request.HTTPMethod = "POST"
request.HTTPBody = // parameters here?
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
(response, data, error) in
println(NSString(data: data, encoding: NSUTF8StringEncoding))
}
Can anyone provide help of how to pass the above parameters in my request? I´m not quite sure how to do that.

The thing is that the HTTPBody expect a NSData object, so you can create Dictionary with the data you need as #dsk explain in this answer and then convert it to JSON to pass as parameters using the dataWithJSONObject function, like in the following way:
var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
request.HTTPMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
var values: [String: AnyObject] = [:]
values["item"] = "value"
values["length"] = "value"
values["names"] = ["value1", "value2"]
values["age"] = "value"
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(values, options: [])
Nevertheless I strongly recommend you use Alamofire to handle all the networking process more easily.
I hope this help you.

Add a variable for your parameters:
var params: [String: AnyObject] = [:]
params["item"] = "YOUR_STRING"
params["length"] = "YOUR_STRING"
params["names"] = ["YOUR_STRING1", "YOUR_STRING2"]
params["age"] = "YOUR_STRING"
Assuming the POST is a JSON request, add them to the HTTPBody as such:
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: [])

Related

How to take a function result and turn it into a key value pair array

I am fairly new to Swift but I have a function that returns a key value pair result of numbers
func dataPostRequest(_ url:String,_ paramString:String)
{
let url:NSURL = NSURL(string: url)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
request.httpBody = paramString.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest) {
(
data, response, error) in
guard let _:NSData = data as NSData?, let _:URLResponse = response, error == nil else {
print("error")
return
}
if let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
{
print(dataString)
}
}
task.resume()
}
I am able to call the function like this:
dataPostRequest("https://myserver.com/","user_email=emailtest.com")
This works correctly but I want to now use the data that I've pulled and display it in a Table View. I have my tableView set up correctly but I am wondering how I can take my function and turn it into a key value pair array or a dictionary that I can use. I have tried creating an empty dictionary and set my function call to it but I get an error:
var emptyDictionary = [Int: Int]()
emptyDictionary = dataPostRequest("https://myserver.com/","user_email=emailtest.com")
And no matter what variation I try I keep getting:
Cannot assign value of type '()' to type '[Int : Int]'
Any guidance would be greatly appreciated.
dataPostRequest has no return value (aka ()). You can decode the received data in the completion handler and assign it to the dictionary. See the comment line below.
If you need to proceed in another function you have to add a completion handler described here.
Basically don't use NS... classes in Swift at all if there are native counterparts. And don't annotate types the compiler can infer.
The native Swift version is
func dataPostRequest(with url:String, paramString : String)
{
let url = URL(string: url)!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = paramString.data(using: .utf8)
let task = session.dataTask(with: request) { data, response, error in
if let error = error {
print(error)
return
}
let dataString = String(data: data!, encoding: .utf8)!
print(dataString)
// here decode the data to the desired type and assign it to emptyDictionary
}
task.resume()
}

parsing array of objects to array of string elements in swift JSON object

I am trying to parse the JSON object received from Web service which gives the result as JSON object of status and data.data again is a array of objects, from this object I want to take one element on the basis of which I have to fill a tableview.
web Service results comes as
{"status":1,"data":[{"service_id":"1","service_name":"Painter"},{"service_id":"2","service_name":"Plumber"},{"service_id":"3","service_name":"Electrician"},{"service_id":"4","service_name":"Handyman"},{"service_id":"5","service_name":"Carpenter"},{"service_id":"6","service_name":"Mason"}]}
parsing in swift I did as:--
created one class
class ABC: NSObject {
var service_name:String?
var service_id : Int?
init(service_name:String,service_id:Int) {
self.service_name = service_name
self.service_id = service_id
}
let myUrl = URL(string: "services.php");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(String(describing: error))")
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json
{
let status=parseJSON["status"] as? Int
let newdata : NSDictionary = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
self.model=(newdata.value(forKey: "data") as? [ABC])!
My problem is I am getting an array of objects in self.model as service_name and service_id keys.Now I want to take out one array of strings that contains all the service_name object values.Its saying not able to convert NSArray to swift array.
As already mentioned by others use (De)codable. It's easy to use and very comfortable. No type cast and no literal keys.
Create two structs, declare the members as non-optional constants with camelCased names and omit the initializer.
struct Root : Decodable {
let status : Int
let data : [Service]
}
struct Service : Decodable {
let serviceName : String
let serviceId : String
}
Then decode the JSON in another class or struct
let myUrl = URL(string: "services.php")
var request = URLRequest(url: myUrl!)
request.httpMethod = "POST"// Compose a query string
let task = URLSession.shared.dataTask(with: request) { data, _, error in
if let error = error { print(error); return }
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let json = try decoder.decode(Root.self, from: data!)
let status = json.status
let newdata = json.data
} catch { print(error))
}
task.resume()
I would recommend to drop JSONSerialization and use Codable protocol instead with CodingKeys.
Here is a simple example to see how it works.
struct Service : Codable {
let id : Int
let name : String
// keys
private enum CodingKeys: String, CodingKey {
case id = "service_id"
case name = "service_name"
}
}
...
// assuming our data comes from server side
let jsonString = "..."
let jsonData = jsonString.data(using: .utf8)!
do {
let jsonDecoder = JSONDecoder()
let user = try jsonDecoder.decode(Service.self, from: jsonData)
print("Getting service: \(service.id) \(service.name)")
} catch {
print("Unexpected error: \(error).")
}
More documentation here.
Use native Swift type Dictionary everywhere you use NSDictionary now
Then get certain value for key by specifing key in dictionary's subscript
if let model = newData["data"] as? [ABC] {
self.model = model
}
Anyway, I would suggest you to start using Codable instead of JSONSerialization
struct Response: Decodable {
let status: Int
let data: [ABC]
}
struct ABC: Decodable {
let serviceName: String
let serviceId: String // note that `serviceId` isn’t `Int` But `String`
}
and then decode your data using JSONDecoder
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let response = try decoder.decode(Response.self, from: data!)
self.model = response.data
} catch { print(error) }

Sending POST request to API using Alamofire

So Im using an API for an app that helps me store data for events where i send data to the API entered/selected by the user store it and get back an ID to reference to later.
Here is some code that Im using.
JSON accepted by API
{
"topic":"test shedule",
"setdate":"21-09-2017",
"scheduledate":"22-09-2017",
"settime":"09:00:00",
"scheduletime":"10:00:00",
"agenda":"hi this is test agenda",
"adminname":"name",
"type":"meeting",
"users": "[{\"category\":\"optional\",\"email\":\"abc#gmail.com\"}]",
"adminemail":"abc#gmail.com"
}
Data Im Sending using Alamofire\
let parameters: Parameters = [
"topic":topicTextField.text!,
"setdate":currentDate as String,
"scheduledate":setDate as String,
"settime":currentTime as String,
"scheduletime":setTime as String,
"agenda":agendaTextField.text!,
"adminname":"abcname",
"type":"meeting",
"users" : "\(smembers)",
"adminemail":"abc#gmail.com"
]
Alamofire.request("\(baseURL)meeting_shedule.php",method: .post, parameters: parameters).responseJSON { response in
if let dict = response.result.value as? Dictionary<String, AnyObject> {
let topic = dict["topic"] as? String
let g_id = dict["g_id"] as? String
self.storeMeeting(topic: topic!, g_id: g_id!)
}
}
smembers is an array created from the dictionary selectedMembers and the dictionary selectedMembers comes from a different ViewController by using prepare for segue
var selectedMembers = [String: String]()
var smembers = [Any]()
var selected = [String: String]()
if selectedMembers.isEmpty == false {
for (key, value) in selectedMembers {
selected = ["email":key, "category":value]
smembers.append(selected)
}
}
The Problem
Im facing a failure response from api.
i think the problem is sending "users" to the API as the API is asking for data in string form and Im sending an array i have even tried to solve this problem by converting smembers to jsonstring by serialization but still returns failure.
Image of error Im receiving
The api works when Im sending request through post man like this.
I have no clue how to approach this problem, how to send the data that the API will accept.
Thanks for your help
Change logic in as shown bellow
var selectedMembers = [String: String]()
var smembers = [String]()
var selected = ""
if selectedMembers.isEmpty == false {
for (key, value) in selectedMembers {
selected = String(format: "{\"\\email\\\":\"\\%#\"\\,\"\\category\"\\:\"\\%#\"\\}", arguments: [key,value])
smembers.append(selected)
}
}
Then in ur post data
let parameters: Parameters = [
"topic":topicTextField.text!,
"setdate":currentDate as String,
"scheduledate":setDate as String,
"settime":currentTime as String,
"scheduletime":setTime as String,
"agenda":agendaTextField.text!,
"adminname":"abcname",
"type":"meeting",
"users" :"[\(smembers.joined(separator: ","))]",
"adminemail":"abc#gmail.com"
]

how to return value from nested array - swift 3

My api query is returning several values in an array (as below), which I need to use for further functions. How do I retrieve the value 60, which is nested?
My code eg let uid = value["uid"] as? String works well to return uid and name.
But for let rest = value["field_resting_bpm"] as? String it returns nil.
How do I correct this line to return the nested value '60'?:
let rest = value["field_resting_bpm"] as? String'
the api query is:
let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
let base64Credentials = credentialData.base64EncodedStringWithOptions([])
let headers = ["Authorization": "Basic \(base64Credentials)"]
var checkUserEndpoint: String = "https://example.site/ios1/user/1.json"
Alamofire.request(.GET, checkUserEndpoint, parameters: nil, headers: headers, encoding: .JSON)
.responseJSON { response in
guard response.result.error == nil else {
print("ran alamofire")
//got an error in getting the data, need to handle it
print("error calling GET")
print(response.result.error!)
return
}
guard let value = response.result.value else {
print("no result data received when calling GET")
return
}
// return UID
print("ran alamofire")
var datareturned = JSON(value)
print("VALUE: \(value)")
it returns this in my console:
uid = 1;
name = "Guest User";
"field_resting_bpm" = {
und = (
{
value = 60;
}
);
UPDATE: this field is an Integer in Drupal user account settings. I have added a text field (so it should return a string), named field_rest_bpm_string, also for testing
the json on the site returns:
"field_resting_bpm":{"und":[{"value":"60"}]},"field_rest_bpm_string":{"und":[{"value":"65","format":null,"safe_value":"65"}]}
NOTE: Code is in Swift 3 but you can easily convert that in swift 2. SwiftyJSON version code is same in 2 and 3.
If you are using SwiftyJSON then things are pretty much simpler
let value = datareturned["field_resting_bpm"]["und"][0]["value"].stringValue
print(value)
If you are not using SwiftyJSON
let rest = value["field_resting_bpm"] as? NSDictionary
let und = (rest?.value(forKey: "und") as! NSArray).object(at: 0) as! NSDictionary
let yourValue = und.value(forKey: "value") as! String
Something like this.

Send array to server starting with iOS 7

I need to send many variables to server. Previously I was using construction like this:
let myURL = NSURL(string: "http://example.com");
let request = NSMutableURLRequest(URL:myURL!);
request.HTTPMethod = "POST";
let postString = "param1=\(var1)&param2=\(var2)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
Now I need to send not only variables like param1 and param2 but few arrays. I know that there is library called Alamofire but it is not supporting iOS 7.
You can do something like this,
let mapDict = [ "a":"First", "b":"Second"]
let json = [ "title":"kk" , "dict": mapDict ]
let jsonData = NSJSONSerialization.dataWithJSONObject(json, options: .PrettyPrinted, error: nil)
// create post request
let url = NSURL(string: "http://example.com/post")!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
// insert json data to the request
request.HTTPBody = jsonData
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data,response,error in
if error != nil{
println(error.localizedDescription)
return
}
if let responseJSON = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [String:AnyObject]{
println(responseJSON)
}
}
task.resume()
You can use array instead of dictionary as per your requirement. hope this will help. :)

Resources