Receive data as NSArray serialize the object and use each value - ios

I'm am trying to use the data of this request. I don't know how to receive data that comes in NSArray. So what I want to know is how can I use each one of the values that are in the array like "addresses" and "awards"?
(I'm using Swifty framework)
This is the server response and the data what I want to use. or better store it in a variable.
[
{
"addresses": [
{
"idAddress": 1,
"idProgram": 1,
"descriptionAddress": "Address1",
"registerDateAddress": "2017-09-12T11:03:53.083",
"isActive": true
}
],
"awards": [
{
"idAward": 1,
"idProgram": 1,
"nameAward": "Awards1",
"descriptionAward": "ImagenAward1",
"imageAward": "ImagenAward1.png",
"registerDateAward": "2017-09-12T11:03:57.67",
"isActive": true
}
]
And this is my code:
func getTheProgram(onSuccess: #escaping(JSON) -> Void, onFailure: #escaping(Error) -> Void) {
print("xxxxxxxxxx", userId ?? "")
guard let url = URL(string: "http://www.my_url.com") else {return}
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("xxxxxxxxx", forHTTPHeaderField: "Authorization")
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if let response = response {
print("Response",response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as! NSArray
print(json )
let result = JSON(data: data)
onSuccess(result)
print("xxxxxx")
} catch {
print(error)
print("xxxxxxx")
}
}
if(error != nil){
onFailure(error!)
print("xxxxxx")
} else{
}
})
task.resume()
}

Related

Swift 5, RxSwift: Network request with RxSwift

I am starting to use RxSwift to make the service call.
This was my old code:
class Service: GraphQLService {
func graphQL(body: [String: Any?], onSuccess: #escaping (Foundation.Data) throws -> (), onFailure: #escaping (Error) -> ()) {
guard let urlValue = Bundle.main.urlValue else { return }
guard let url = URL(string: urlValue) else { return
print("Error with info.plist")
}
var request = URLRequest(url: url)
let userKey = Bundle.main.userKeyValue
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(userKey, forHTTPHeaderField: "userid")
request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .fragmentsAllowed)
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
onFailure(error)
}
if let data = data {
do{
try onSuccess(data)
}
catch{
onFailure(error)
}
}
}.resume()
}
And here I do the function to get time deposits:
final class TimeDepositManager: Service, TimeDepositManagerProtocol {
let timeDepositQuery = Bundle.main.queryValue
func getTimeDeposits(onSuccess: #escaping ([TimeDeposits]) -> (), onFailure: #escaping (Error) -> ()) {
let body = ["query": timeDepositQuery]
Service().graphQL(body: body, onSuccess: { data in
let json = try? JSONDecoder().decode(GraphQLResponse.self, from: data)
onSuccess(json?.data?.account?.timeDeposits ?? [])
}, onFailure: onFailure)
}
And so far this is my code with RxSwift:
class Service: GraphQLService {
func graphQL(body: [String : Any?]) -> Observable<Foundation.Data> {
return Observable.create { observer in
let urlValue = Bundle.main.urlValue
let url = URL(string: urlValue ?? "")
let session = URLSession.shared
var request = URLRequest(url: url!)
let userKey = Bundle.main.userKeyValue
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(userKey, forHTTPHeaderField: "userid")
request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .fragmentsAllowed)
session.dataTask(with: request) { (data, response, error) in
if let error = error {
observer.onError(error)
}
if let data = data {
do{
try onSuccess(data)
observer.onNext(data)
}
catch{
//onFailure(error)
observer.onError(error)
print("Error: \(error.localizedDescription)")
}
}
}.resume()
return Disposables.create {
session.finishTasksAndInvalidate()
}
}
}
This is where I don't understand how in my getTimeDeposits () I can do the deserialization with try? JSONDecoder () ... with RxSwift without using onSuccess?
final class TimeDepositManager: Service, TimeDepositManagerProtocol {
let timeDepositQuery = Bundle.main.queryValue
func getTimeDeposits() -> Observable<[TimeDeposits]> {
let body = ["query": timeDepositQuery]
Service().graphQL(body: body)
}
You can have getTimeDeposits() return an Observable as well and handle the deserialization in a map closure. A couple of other things.
RxCocoa already has a method on URLSession so you don't need to write your own.
I suggest reducing the amount of code you have in a function that makes the network request. You want to be able to test your logic for making the request without actually making it.
Something like this:
final class TimeDepositManager: Service, TimeDepositManagerProtocol {
let timeDepositQuery = Bundle.main.queryValue
func getTimeDeposits() -> Observable<[TimeDeposits]> {
let body = ["query": timeDepositQuery]
return Service().graphQL(body: body)
.map { try JSONDecoder().decode(GraphQLResponse.self, from: $0).data?.account?.timeDeposits ?? [] }
}
}
class Service: GraphQLService {
func graphQL(body: [String: Any?]) -> Observable<Data> {
guard let urlValue = Bundle.main.urlValue else { fatalError("Error with info.plist") }
let request = urlRequest(urlValue: urlValue, body: body)
return URLSession.shared.rx.data(request: request) // this is in RxCocoa
}
func urlRequest(urlValue: String, body: [String: Any?]) -> URLRequest {
guard let url = URL(string: urlValue) else { fatalError("Error with urlValue") }
var request = URLRequest(url: url)
let userKey = Bundle.main.userKeyValue
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(userKey, forHTTPHeaderField: "userid")
request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .fragmentsAllowed)
return request
}
}
If you don't want to use RxCocoa for some reason, here is the correct way to wrap the URLSession.dataTask method:
extension URLSession {
func data(request: URLRequest) -> Observable<Data> {
Observable.create { observer in
let task = self.dataTask(with: request, completionHandler: { data, response, error in
guard let response = response as? HTTPURLResponse else {
observer.onError(URLError.notHTTPResponse(data: data, response: response))
return
}
guard 200 <= response.statusCode && response.statusCode < 300 else {
observer.onError(URLError.failedResponse(data: data, response: response))
return
}
guard let data = data else {
observer.onError(error ?? RxError.unknown)
return
}
observer.onNext(data)
observer.onCompleted() // be sure to call `onCompleted()` when you are done emitting values.
// make sure every possible path through the code calls some method on `observer`.
})
return Disposables.create { task.cancel() } // don't forget to handle cancelation properly. You don't want to kill *all* tasks, just this one.
}
}
}
enum URLError: Error {
case notHTTPResponse(data: Data?, response: URLResponse?)
case failedResponse(data: Data?, response: HTTPURLResponse)
}

How to Pass Key Value Parameter in JSON POST method in Swift?

This is API http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/
its parameter: "contactsList" : ["5987606147", "6179987671", "5082508888"]
its header: ["deviceid": "584D97F-761A-4C24-8C4B-C145A8B8BD75", "userType": "personal", "key": "9609cc826b0d472faf9967370c095c21"]
In my code if i put breakpoint then filtertaggedUser() is calling but i am unable to go inside completionHandler the access is not going inside dataTask
Access going to else part why? the api is working.
i am trying to pass parameter key value in URL string like below
let urlStr = "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/?contactsList=" + "8908908900"
is this correct approch?
code for above API:
func filtertaggedUser() {
print("inside filter taggedusers")
let headers = ["deviceid": "584D97F-761A-4C24-8C4B-C145A8B8BD75", "userType": "personal", "key": "9609cc826b0d472faf9967370c095c21"]
let urlStr = "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/?contactsList=" + "8908908900"
let request = NSMutableURLRequest(url: NSURL(string:urlStr)! as URL,cachePolicy: .useProtocolCachePolicy,timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
// access not coming here
let httpResponse = response as? HTTPURLResponse
if httpResponse!.statusCode == 200 {
print("filter taggedusers inside")
do {
print("filter taggedusers inside do")
let jsonObject = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! [String :AnyObject]
print("filter taggedusers \(jsonObject)")
} catch { print(error.localizedDescription) }
} else { Constants.showAlertView(alertViewTitle: "", Message: "Something went wrong, Please try again", on: self) }
})
dataTask.resume()
}
OUTPUT:
POSTMAN OUTPUT
POSTMAN Body
why response is not coming, where i did mistake, please help me with the code.
We can call the Post request API like below,
func getPostString(params:[String:Any]) -> String
{
var data = [String]()
for(key, value) in params
{
data.append(key + "=\(value)")
}
print(data.map { String($0) }.joined(separator: "&"))
return data.map { String($0) }.joined(separator: "&")
}
func callPostApi(){
let url = URL(string: "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/")
guard let requestUrl = url else { fatalError() }
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
request.setValue("584D97F-761A-4C24-8C4B-C145A8B8BD75", forHTTPHeaderField: "deviceid")
request.setValue("9609cc826b0d472faf9967370c095c21", forHTTPHeaderField: "key")
request.setValue("personal", forHTTPHeaderField: "userType")
let parameters = getPostString(params: ["contactsList":["8908908900"]])
request.httpBody = parameters.data(using: .utf8)
// Perform HTTP Request
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
let httpResponse = response as? HTTPURLResponse
print(httpResponse!.statusCode)
// Check for Error
if let error = error {
print("Error took place \(error)")
return
}
// Convert HTTP Response Data to a String
if let data = data, let dataString = String(data: data, encoding: .utf8) {
print("Response data string:\n \(dataString)")
}
}
task.resume()
}
Output :
{"8908908900":{"userId":"9609cc826b0d472faf9967370c095c21","userName":"Satish Madhavarapu","profilePic":null,"oniTaag":true,"tagged":false,"userType":"personal"}}

post parameter to sever using dictionary swift

I am trying to send data to the server using a dictionary but unfortunately the data is not saving to the database (fields were found to be blank) and I am getting the below response:
Optional(["status": true, "msg": successfull])
And also tried to show UIActivityIndicator to user until he got a response but couldn't find a way.
Code attempted:
let dict = [ "key_one": self.tf1.text!,"key_two":self.tf2.text!]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(dict, options: .PrettyPrinted)
// create post request
let url = NSURL(string: "myAPIUrl.php?")!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
// insert json data to the request
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.HTTPBody = jsonData
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in
if error != nil{
print("Error -> \(error)")
return
}
do {
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String:AnyObject]
print("Response -> \(result)")
} catch {
print("Inside Error Section -> \(error)")
}
}
task.resume()
} catch {
print(error)
}
// write this in one fucantion
let Username:NSString = EmailTextField.text! as NSString
let password:NSString = PasswordTextField.text! as NSString
let headers = [
"content-type": "application/json",
"cache-control": "no-cache",
"postman-token": "121b2f04-d2a4-72b7-a93f-98e3383f9fa0"
]
let parameters = [
"username": "\(Username)",
"password": "\(password)"
]
if let postData = (try? JSONSerialization.data(withJSONObject: parameters, options: [])) {
var request = NSMutableURLRequest(url: URL(string: "YOUR_URL_HERE")!,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData
let session = URLSession.shared
let task = URLSession.shared.dataTask(with: request as URLRequest) {
(data, response, error) -> Void in
if (error != nil) {
print(error)
} else {
DispatchQueue.main.async(execute: {
if let json = (try? JSONSerialization.jsonObject(with: data!, options: [])) as? NSDictionary
{
let success = json["status"] as? Int
let message = json["message"] as? String
// here you check your success code.
if (success == 1)
{
print(message)
let vc = UIActivityViewController(activityItems: [image], applicationActivities: [])
present(vc, animated: true)
}
else
{
// print(message)
}
}
})
}
}
task.resume()
}

POST w/ JSON Body - Swift3 - fragments?

I'm simply trying to send a JSON string via a Swift3 httprequest.
Tried using a Dictionary, and an escaped string ...
func getToken(successHandler: #escaping (Any) -> Void, errorHandler: #escaping (Any) -> Void) {
var request = URLRequest(url: URL(string: "http://my-api.domain.com/getToken")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
do
{
// try with Dictionary
let bodyJson: [String: String] = [
"username": "theusername"
]
let bodyJsonData = try JSONSerialization.data(withJSONObject: bodyJson, options: [])
// try with escaped String
let jsonString = "{" +
"\"username\": \"theusername\"," +
"}"
let jsonStringData = jsonString.data(using: String.Encoding.utf8)
//request.httpBody = bodyJsonData
request.httpBody = jsonStringData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
print(error)
errorHandler(error)
return
}
guard let data = data else {
print("Data is empty")
errorHandler("Data is empty")
return
}
var json: Any? = nil
do
{
json = try JSONSerialization.jsonObject(with: data, options: [])
DispatchQueue.main.asyncAfter(deadline: .now()) {
successHandler(json)
}
}
catch let error as NSError {
errorHandler(error)
}
}
task.resume()
}
catch
{
errorHandler(error)
}
}
I keep getting:
Handle Error: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did
not start with array or object and option to allow fragments not set."
UserInfo={NSDebugDescription=JSON text did not start with array or
object and option to allow fragments not set.}
I can't find how to try allowing fragments, all of the examples/tutorials are for Swift2.x :/
Unsure what to do!
// prepare json data
let mapDict = [ "1":"First", "2":"Second"]
let json = [ "title":"ABC" , "dict": mapDict ] as [String : Any]
do {
let jsonData = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
// create post request
let endpoint: String = "https://yourAPI"
let session = URLSession.shared
let url = NSURL(string: endpoint)!
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
let task = session.dataTask(with: request as URLRequest){ data,response,error in
if error != nil{
print(error?.localizedDescription)
return
}
}
task.resume()
} catch {
print("bad things happened")
}

Add POST,PUT,DELETE request class for swift

I have create a client service class to make call GET request from web api. I tried to extended but have more web method POST,PUT,Delete.I don't find good example in how to create POST,PUT,Delete using swift closure.I just want to ask how to add POST,PUT,Delete to client service?
import Foundation
class ClientService{
func getClients(searchstring:String,pageNumber:Int,callBack:(NSArray)->()){
request("\(_settings.baseUrl)Client/\(searchstring)/\(String(pageNumber))/rrn/brns", callBack: callBack)
}
func request(url:String,callBack:(NSArray)->()){
let nsURL = NSURL(string:url);
let task = NSURLSession.sharedSession().dataTaskWithURL(nsURL!){
(data,response,error) in
do {
let response = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
callBack(response)
} catch let error as NSError {
print("json error: \(error.localizedDescription)")
}
}
task.resume()
}
init(){
self._settings = Settings();
}
var _settings:Settings!;
}
You are on the right track. I make a separate function for get, post, put, delete etc. But you could make them in a one function if you want.
Bear in mind, this code is just to illustrate how to do it. You will need to modify it for your needs.
func request(url:String, method: String, params: [String: String], completion: ([AnyObject])->() ){
if let nsURL = NSURL(string:url) {
let request = NSMutableURLRequest(URL: nsURL)
if method == "POST" {
// convert key, value pairs into param string
postString = params.map { "\($0.0)=\($0.1)" }.joinWithSeparator("&")
request.HTTPMethod = "POST"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
}
else if method == "GET" {
postString = params.map { "\($0.0)=\($0.1)" }.joinWithSeparator("&")
request.HTTPMethod = "GET"
}
else if method == "PUT" {
putString = params.map { "\($0.0)=\($0.1)" }.joinWithSeparator("&")
request.HTTPMethod = "PUT"
request.HTTPBody = putString.dataUsingEncoding(NSUTF8StringEncoding)
}
// Add other verbs here
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data, response, error) in
do {
// what happens if error is not nil?
// That means something went wrong.
// Make sure there really is some data
if let data = data {
let response = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)
completion(response)
}
else {
// Data is nil.
}
} catch let error as NSError {
print("json error: \(error.localizedDescription)")
}
}
task.resume()
}
else{
// Could not make url. Is the url bad?
// You could call the completion handler (callback) here with some value indicating an error
}
}
Call it like this:
request("http://somedomain.etc", "POST", ["key1" : "value1", "key2", "values2"]) {
(result) in
// Handle result here.
}
You will note that I eliminated NSArray. [AnyObject] is the Swift way to do this.
I recommend that you add some sort of error indicator in the completion handler. That would let you detect that something went wrong and handle it.
Be very cautious when using ! to unwrap variables. This is the most common reason for apps crashing.
i use for mes projects Alamofire (Elegant HTTP Networking in Swift), and i love it
so example how to use POST
let parameters = [
"foo": "bar",
"baz": ["a", 1],
"qux": [
"x": 1,
"y": 2,
"z": 3
]
]
Alamofire.request(.POST, "https://httpbin.org/post", parameters: parameters)
// HTTP body: foo=bar&baz[]=a&baz[]=1&qux[x]=1&qux[y]=2&qux[z]=3
and here how to use Delete
Alamofire.request(.DELETE, "https://httpbin.org/delete")
go to documentation is very good
https://github.com/Alamofire/Alamofire
and if you want use swift without framework
this is example how to use POST
var request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:4567/login"))
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var params = ["username":"jameson", "password":"password"] as Dictionary<String, String>
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
Instead of using dataTaskWithUrl, you could create an HTTP request like this:
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = jsonData
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(String (jsonData?.length), forHTTPHeaderField: "Content-Length")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { data, res, error in
// etc etc
Everything else in your example above would be the same. You'd have to provide the json data, of course. For that, you could do something like this:
let data: [String: AnyObject] = ["nameValue": dataValue]
var jsonData: NSData? = nil
do {
jsonData = try NSJSONSerialization.dataWithJSONObject(data, options: NSJSONWritingOptions(rawValue: 0))
} catch {
// some error serializing
}
Swift 4 version (I think):
func restRequest(url:String, method: String, params: [String: String], completion: #escaping ([AnyObject])->() ){
if let nsURL = NSURL(string:url) {
let request = NSMutableURLRequest(url: nsURL as URL)
if method == "POST" {
// convert key, value pairs into param string
let postString = params.map { "\($0.0)=\($0.1)" }.joined(separator: "&")
request.httpMethod = "POST"
request.httpBody = postString.data(using: String.Encoding.utf8)
}
else if method == "GET" {
let postString = params.map { "\($0.0)=\($0.1)" }.joined(separator: "&")
request.httpMethod = "GET"
}
else if method == "PUT" {
let putString = params.map { "\($0.0)=\($0.1)" }.joined(separator: "&")
request.httpMethod = "PUT"
request.httpBody = putString.data(using: String.Encoding.utf8)
}
// Add other verbs here
let task = URLSession.shared.dataTask(with: request as URLRequest) {
(data, response, error) in
do {
// what happens if error is not nil?
// That means something went wrong.
// Make sure there really is some data
if let data = data {
let response = try JSONSerialization.JSONObjectWithData(data, options: JSONSerialization.ReadingOptions.MutableContainers)
completion(response)
}
else {
// Data is nil.
}
} catch let error as NSError {
print("json error: \(error.localizedDescription)")
}
}
task.resume()
}
else{
// Could not make url. Is the url bad?
// You could call the completion handler (callback) here with some value indicating an error
}
}

Resources