2

I'm not using Alamofire, so i want to use JSON post approach in SharedClass and i want to send my api name and all parameters to that function. Finally i want to get the response back. I tried but it's not working. If it's not correct please correct me or if any other options are available please suggest me.

My code in SharedClass

func postRequestFunction(apiName:String , parameters:String ) -> [String:Any] {

    var localURL =  "hostname/public/index.php/v/***?"

        localURL = localURL.replacingOccurrences(of: "***", with: apiName)

        var request = URLRequest(url: URL(string: localURL)!)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        print("shared URL : \(request)")
        request.httpBody = parameters.data(using: .utf8)

    var returnRes:[String:Any] = [:]
        let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data, error == nil else { // check for fundamental networking error
            print(error!)
            //                print("error=\(String(describing: error))")
                            print("localizedDescription : \(String(describing: error?.localizedDescription))")
            return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
            }

            do {
                returnRes = try JSONSerialization.jsonObject(with: data, options: []) as! [String : Any]
                print(returnRes)

            } catch let error as NSError {
                print(error)
            }
        }

        task.resume()

    return returnRes
}

In my view controller class my code is. Here i'm calling function

func getProjectDetails() {
    let response = SharedClass.sharedInstance.postRequestFunction(apiName: "API Name", parameters: parameters)
    print(response)
    let res = response["Response"] as! [String:Any]
    let status = res["status"] as! String

    if status == "SUCCESS" {
        //I will handle response here
    } else {
        let message = res["message"] as! String
        //Call alert function
        SharedClass.sharedInstance.alert(view: self, title: "", message: message)
    }
}
Naresh
  • 16,698
  • 6
  • 112
  • 113

2 Answers2

1

You forgot the asynchronous paradigm of Service, You can return your API response in Closure, as like below

func postRequestFunction(apiName:String , parameters:String, returnRes: @escaping ([String: Any]) -> () ) {

    var localURL =  "hostname/public/index.php/v/***?"

    localURL = localURL.replacingOccurrences(of: "***", with: apiName)

    var request = URLRequest(url: URL(string: localURL)!)
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    print("shared URL : \(request)")
    request.httpBody = parameters.data(using: .utf8)

    let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data, error == nil else {
        // check for fundamental networking error
        return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(String(describing: response))")
        }

        do {
            if let response = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any] {
                returnRes(response)
            }
        } catch let error as NSError {
            print(error)
        }
    }

    task.resume()
}

And use like below

postRequestFunction(apiName: "yourUrl", parameters: "Param") { (response) in

    print(response)

}
Jaydeep Vora
  • 6,085
  • 1
  • 22
  • 40
  • I'm calling like this SharedClass.sharedInstance.postRequestFunction(apiName: "apiname", parameters: parameters) { (response) in print(response) ,, Response getting in shared class, but it's not returning any thing – Naresh Aug 25 '18 at 07:08
  • print(response) it's not printing anything, I'm getting data from server in shared class. How to get response from shared class to my custom class after getting data. Please help me... – Naresh Aug 25 '18 at 07:10
  • Nothing, In SharedClass response printing successfully, but that response not getting in my class – Naresh Aug 25 '18 at 07:30
  • Is it possible with NSNotificationCenter to send response back to ViewController – Naresh Aug 27 '18 at 05:02
  • If possible with delegates or Notification Center please advise me. – Naresh Aug 27 '18 at 05:14
  • Hay Jaydeep, i got answer. Once again thank you for your answer – Naresh Aug 30 '18 at 08:50
1

Here is my solution:

class APIManager {

    private init () {}

    static let shared = APIManager()

    func postRequestFunction(apiName: String , parameters: String, onCompletion: @escaping (_ success: Bool, _ error: Error?, _ result: [String: Any]?)->()) {

        var localURL =  "hostname/public/index.php/v/***?"

        localURL = localURL.replacingOccurrences(of: "***", with: apiName)

        var request = URLRequest(url: URL(string: localURL)!)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        print("shared URL : \(request)")
        request.httpBody = parameters.data(using: .utf8)

        var returnRes:[String:Any] = [:]
        let task = URLSession.shared.dataTask(with: request) { data, response, error in

            if let error = error {
                onCompletion(false, error, nil)
            } else {
                guard let data = data else {
                    onCompletion(false, error, nil)
                    return
                }

                if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 200 {
                    do {
                        returnRes = try JSONSerialization.jsonObject(with: data, options: []) as! [String : Any]
                        onCompletion(true, nil, returnRes)

                    } catch let error as NSError {
                        onCompletion(false, error, nil)
                    }
                } else {
                    onCompletion(false, error, nil)
                }
            }
        }
        task.resume()
    }
}

func getProjectDetails() {

    /* Notes:

     ** onCompletion Block Parameters:

     success - This indicates whether the API called successfully or not.
     error - This indicates errors from either API calling failed, JSON parsing, or httpStatus is not 200.
     result - This indicates the JSON parsed result.

     ** APIManager:

     I have renamed your SharedClass to APIManager for better readibility.

     ** sharedInstance:

     I have renamed sharedInstance to shared for better readibility.

    */

    APIManager.shared.postRequestFunction(apiName: "API Name", parameters: "parameters") { (success, error, result) in
        if success {
            if let res = result?["Response"] as? [String: Any] {
                if let status = res["status"] as? String {
                    if status == "SUCCESS" {
                        //You can handle response here.
                    } else {
                        let message = res["message"] as! String
                        //Call alert function.
                    }
                }
            }
        } else {
            print(error?.localizedDescription)
        }
    }
}
Hemang
  • 26,840
  • 19
  • 119
  • 186
  • Dear Hemang, is it possible to hit multiple API's from same class. Like this Ex: https://stackoverflow.com/questions/28634995/chain-multiple-alamofire-requests – Naresh Aug 30 '18 at 09:26
  • 1
    Hi, glad you liked the answer, I believe, it's possible but the question you pointed to, it's using a third party library, PromiseKit. Without using you can do it, but then you required to write lots of code for it. Perhaps, `NSOperationManager` and use of `GCD` calls? – Hemang Aug 30 '18 at 09:57
  • I have som basic knowledge on NSOperationManager, can you please send that code for me. Is it possible tosend – Naresh Aug 30 '18 at 10:01
  • 1
    Your blog is good , few minutes back i saw it...Greate job Hemang – Naresh Aug 30 '18 at 10:02
  • Thank you, but now a days I am not active on my blog. :( I will try to add more content. Regarding your query, I can't send you that code because as I told, you will require to write so much of code, so I can't help on it at the moment. Would I rather suggest you explore it with `PromiseKit` maybe it will be more easy for you? – Hemang Aug 30 '18 at 10:05
  • If possible please add that code to your blog and please inform to me. I'm waiting for your response. Thank you very much for your quick response. Bye – Naresh Aug 30 '18 at 10:08