Search code examples
iospostgresqlswiftpoststrongloop

How do I perform GET and POST requests in Swift?


I adapted this from Ray Wenderlich's iOS Apprentice tutorial part 4.

This code works as a GET request sent to my Strongloop API with a simple database model, however:

  1. This works, but I don't know why it works, since it invokes no method that I can see to actually send the request.

  2. I see no means to make it into a POST request.

My question is: How do I perform a POST request? Is it done in a completely different way?

Let me know if you need more information.

    class ViewController: UIViewController {


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func getFromDB() {
        let url = urlWithSearchText("")
        println("URL: '\(url)'")
        if let jsonString = performGetRequestWithURL(url) {
            println("Received JSON string '\(jsonString)'")
        }
    }


    func urlWithSearchText(searchText: String) -> NSURL {
        let escapedSearchText = searchText.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
        let urlString = String(format: "http://localhost:3000/api/Tests", escapedSearchText)
        let url = NSURL(string: urlString)
        return url!
    }    

    func performGetRequestWithURL(url: NSURL) -> String? {
        var error: NSError?
        if let resultString = String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error) {
            return resultString
        } else if let error = error {
            println("Download Error: \(error)")
        } else {
            println("Unknown Download Error")
        }
        return nil
    }

Here is a picture of this working:

https://dl.dropboxusercontent.com/u/14464971/Images/Messages%20Image%281477993527%29.png


Solution

  • Below are two POST methods. Depending on if you want it synchronous (everything else waits until the post method is completed) or asynchronous (POST method runs in background, other methods run in parallel).

    Methods

    // POST data to url
    func postDataAsynchronous(url: String, bodyData: String, completionHandler: (responseString: String!, error: NSError!) -> ()) {
        var URL: NSURL = NSURL(string: url)!
        var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
        request.HTTPMethod = "POST";
        request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
    
        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()){
    
            response, data, error in
    
            var output: String!
    
            if data != nil {
                output = NSString(data: data, encoding: NSUTF8StringEncoding) as! String
            }
    
            completionHandler(responseString: output, error: error)
        }
    }
    
    // Obtain the data
    func postDataSynchronous(url: String, bodyData: String, completionHandler: (responseString: String!, error: NSError!) -> ())
    {
        let URL: NSURL = NSURL(string: url)!
        var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
        request.HTTPMethod = "POST"
        request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
        request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    
        var response: NSURLResponse?
        var error: NSError?
    
        // Send data
        let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
    
        var output: String! // Default to nil
    
        if data != nil{
            output =  NSString(data: data!, encoding: NSUTF8StringEncoding) as! String
        }
    
        completionHandler(responseString: output, error: error)
    
    }
    

    Using them

    You can then call (use) them like so:

    postDataSynchronous(url, bodyData: bodyData) {
        responseString, error in
    
            if error != nil {
                println("Error during post: \(error)")
                return
            }
            else{
                //Success
                println(responseString)
                userType = responseString // Set usertype based on server response
            }        
        }
    

    SWIFT 2.0

    func postData(url: String, params: Dictionary<String, String>, completionHandler: (data: NSData?, response: NSURLResponse?, error: NSError?) -> ()) {
    
        // Indicate download
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true
    
        let url = NSURL(string: url)!
        //        print("URL: \(url)")
        let request = NSMutableURLRequest(URL: url)
        let session = NSURLSession.sharedSession()
        request.HTTPMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
    
        // Verify downloading data is allowed
        do {
            request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: [])
        } catch let error as NSError {
            print("Error in request post: \(error)")
            request.HTTPBody = nil
        } catch {
            print("Catch all error: \(error)")
        }
    
        // Post the data
        let task = session.dataTaskWithRequest(request) { data, response, error in
            completionHandler(data: data, response: response, error: error)
    
            // Stop download indication
            UIApplication.sharedApplication().networkActivityIndicatorVisible = false // Stop download indication
    
        }
    
        task.resume()
    
    }