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)¶m2=\(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. :)
Related
I am new in swift and trying to send Data to Api which is in the form of Data object and i am trying to pass that data in JSON
let val:Data = myFile.DataRepresentation()
let json: [String: Any] = ["file": val,
"dict": ["1":"First", "2":"Second"]]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
it giving me error "Invalid type in JSON.write"
or help me how can i pass Data in NSMUtableURLRequest
Try to implement this code example, it should work:
let json: [String: Any] = ["name": "morpheus",
"job": "leader"]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
// create post request
let url = URL(string: "https://reqres.in/api/users")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}
task.resume()
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()
}
I have an app where a user reviews an array of users. Example:
["user1","user2","user3","user4"]
When the user reviews the first user the app should present the second user for voting. Unfortunately when a user votes on the user2, user3, user4; the value for user1 is what's put in the database. I tested the PHP via postman and there's no issue there, so it has to be in the swift code. Here is my code:
func loadCards()->[String] {
let username = user!["username"] as! String
let url = URL(string: "http://localhost/shotsCenter.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
let body = "username=\(username)"
request.httpBody = body.data(using: .utf8)
// launch session
URLSession.shared.dataTask(with: request) { data, response, error in
// getting main queue of proceeding inf to communicate back, in another way it will do it in background
// and user will no see changes :)
DispatchQueue.main.async(execute: {
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: AnyObject]
// clean up
self.valueArray.removeAll(keepingCapacity: false)
self.circleArray.removeAll(keepingCapacity: false)
// delcare new secure var to store json
guard let parseJSON = json else {
print("Error while parsing")
return
}
// declare new secure var to store $returnArray["users"]
guard let parseUSERS = parseJSON["users"] else {
print(parseJSON["message"])
return
}
self.valueArray = parseUSERS as! [AnyObject]
if self.valueArray.count > 0 {
let num_currentLoadedCardsArrayCap = (self.valueArray.count > MAX_BUFFER_SIZE) ? MAX_BUFFER_SIZE : self.valueArray.count
for (i, value) in self.valueArray.enumerated() {
let ava = self.valueArray[i]["ava"]
let id = self.valueArray[i]["id"]
let age = (NSString(format: "%#", self.valueArray[i]["age"] as! CVarArg))
let city = self.valueArray[i]["city"]
let state = self.valueArray[i]["state"]
self.age.append(age as AnyObject)
self.city.append(city as AnyObject)
self.state.append(state as AnyObject)
let url = NSURL(string: ava! as! String)!
let imageData = try? Data(contentsOf: url as URL)
let image = UIImage(data: imageData!)!
self.circleArray.append(image)
let reviewed = self.valueArray[i]["username"]
self.reviewed.append((reviewed as AnyObject) as! String)
print("reviewed user", reviewed! as Any)
let newCard = self.createDraggableViewWithData(at: i, value:value as! NSDictionary)
self.allCardsArray.append(newCard)
if i < num_currentLoadedCardsArrayCap {
self.currentLoadedCardsArray.append(newCard)
}
}
for (i,_) in self.currentLoadedCardsArray.enumerated() {
if i > 0 {
self.viewTinderBackGround.insertSubview(self.currentLoadedCardsArray[i], belowSubview: self.currentLoadedCardsArray[i - 1])
}
else {
self.viewTinderBackGround.addSubview(self.currentLoadedCardsArray[i])
}
self.currentIndex += 1
}
self.animateCardAfterSwiping()
self.perform(#selector(self.createDummyCard), with: nil, afterDelay: 1.0)
}
} catch {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = "\(error)"
})
return
}
} else {
DispatchQueue.main.async(execute: {
let message = error!.localizedDescription
})
return
}
})
} .resume()
return reviewed
}
func insertShot(_ rating: String, _ reviewed2: NSDictionary) {
let reviewer = user!["username"] as! String
let reviewed2 = reviewed[index]
let url = URL(string: "http://localhost/shotsCenter.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// param to be passed to php file
let param = [
"user" : reviewer,
"revieweduser" : reviewed2,
"rating" : rating
] as [String : Any]
// body
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
// ... body
request.httpBody = createBodyWithParams(param as? [String : String], boundary: boundary)
// launch session
URLSession.shared.dataTask(with: request) { data, response, error in
// get main queu to communicate back to user
DispatchQueue.main.async(execute: {
if error == nil {
do {
// json containes $returnArray from php
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
// declare new var to store json inf
guard let parseJSON = json else {
print("Error while parsing")
return
}
// get message from $returnArray["message"]
let message = parseJSON["message"]
//print(message)
// if there is some message - post is made
if message != nil {
// reset UI
// self.msgTxt.text = ""
// switch to another scene
//self.tabBarController?.selectedIndex = 3
//_ = self.navigationController?.popViewController(animated: true)
}
} catch {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = "\(error)"
appDelegate.infoView(message: message, color: colorSmoothRed)
})
return
}
} else {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = error!.localizedDescription
appDelegate.infoView(message: message, color: colorSmoothRed)
})
return
}
})
}.resume()
}
No idea what currentIndex is for. Sth about the view hierarchy?
index is an interesting candidate. The only times it is used is in
let reviewed2 = reviewed[index]
and I see no modification to it. Since usernames are stored in there with
let reviewed = self.valueArray[i]["username"]
I think you are sending the same username for all four ratings, since reviewed2 is then made of the .httpBody. That's a guess from what I can see.
Tip: Codable
Codable may save you a lot of the ugliness of juggling around with AnyObject & co, since you'll have a [User] array instead of.. 4 separate arrays which you access with [index]. https://app.quicktype.io will get you started quickly by providing you with the parsing code for the given JSON.
I want to populate an array I have with JSON data. I'm using SwiftyJSON and Alamofire. I'm new to parsing JSON, so i apologize for any ignorance on my end. The URL below is the url i'm inserting in getAllTimeAverage(). Any help would be awesome!! thanks!
This is the JSON Data
https://apiv2.bitcoinaverage.com/indices/global/history/BTCILS?period=alltime&format=json
This is the array i want to populate
var allTimeAverages: [Any] = []
These are my functions. I call them in my cellForRowAt:, when i print the allTimeAverages.count, I get back zero.
func getAllTimeAverage(url: String) {
Alamofire.request(url, method: .get)
.responseJSON { response in
if response.result.isSuccess {
print("Sucess! Got the Bitcoin Data")
let bitcointJSON : JSON = [JSON(response.result.value!)]
self.updateAverageAllTime(json: bitcointJSON)
} else {
print("Error: \(String(describing: response.result.error))")
self.price = "Connection Issues"
}
}
}
func updateAverageAllTime(json: JSON) {
if let allTimeAverage = json["average"].dictionaryObject {
self.allTimeAverages.append(allTimeAverage)
}
}
func getBitcoinData(url: String) {
Alamofire.request(url, method: .get)
.responseJSON { response in
if response.result.isSuccess {
print("Sucess! Got the Bitcoin Data")
let bitcointJSON : JSON = JSON(response.result.value!)
self.updateBitcoinData(json: bitcointJSON)
} else {
print("Error: \(String(describing: response.result.error))")
self.price = "Connection Issues"
}
}
}
Here is an example of how this is to be done (I have taken a few values from the JSON API you have shared):
let jsonString = "[{\"high\": 23043.41,\"open\": 21494.60,\"low\": 21338.34,\"average\": 21668.01,\"time\": \"2018-06-29 00:00:00\",\"volume\": 102148.30132998565},{\"high\": 22488.75,\"open\": 22405.51,\"low\": 21380.97,\"average\": 22241.29,\"time\": \"2018-06-28 00:00:00\",\"volume\": 69383.44795111718},{\"high\": 22491.85,\"open\": 22169.36,\"low\": 21940.47,\"average\": 22224.29,\"time\": \"2018-06-27 00:00:00\",\"volume\": 69884.07809550199},{\"high\": 22707.46,\"open\": 22635.32,\"low\": 22004.29,\"average\": 22480.86,\"time\": \"2018-06-26 00:00:00\",\"volume\": 71611.8914173987}]";
if let jsonData = jsonString.data(using: .utf8, allowLossyConversion: false) {
let json = JSON(data: jsonData)
let jsonArray = json.arrayValue
let averagesArray = jsonArray.map{ $0["average"].doubleValue}
let highArray = jsonArray.map{ $0["high"].doubleValue}
let lowArray = jsonArray.map{ $0["low"].doubleValue}
let volumeArray = jsonArray.map{ $0["volume"].doubleValue}
let openArray = jsonArray.map{ $0["open"].doubleValue}
}
Making your solution work according to the above:
In the following line, remove [] as you are already getting an array from the API.
let bitcoinJSON : JSON = [JSON(response.result.value!)]
so the above line will become
let bitcoinJSON : JSON = JSON(response.result.value!)
Now, you can get the array value like I have done:
let jsonArray = bitcoinJSON.arrayValue
and now you can utilize the rest of the code (repeated below):
let averagesArray = jsonArray.map{ $0["average"].doubleValue}
let highArray = jsonArray.map{ $0["high"].doubleValue}
let lowArray = jsonArray.map{ $0["low"].doubleValue}
let volumeArray = jsonArray.map{ $0["volume"].doubleValue}
let openArray = jsonArray.map{ $0["open"].doubleValue}
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: [])