Can someone find the error and verify my Swift NSURLSession code?

669 views Asked by At

I am writing my first, basic IOS app using Swift that will poll a Proliphix IP Thermostat and display the temperature. I have converted an HTTP Post to NSURLSession using Paw, but the converted code appears to have a 3 syntax errors when I load it in Xcode Playground.

My goal right now is to get this working in Playground, but ultimately use it in my App code. Could someone please load this code in your own Xcode Playground and fix the error and make it work? The URL is a public IP address of the thermostat and If working correctly, it will poll the thermostat and return a value for OID4.3.2.3 and = something like 772& (currently 77.2 degrees).

class MyRequestController {
    func sendRequest() {
        /* Configure session, choose between:
           * defaultSessionConfiguration
           * ephemeralSessionConfiguration
           * backgroundSessionConfigurationWithIdentifier:
         And set session-wide properties, such as: HTTPAdditionalHeaders,
         HTTPCookieAcceptPolicy, requestCachePolicy or timeoutIntervalForRequest.
         */
        let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()

        /* Create session, and optionally set a NSURLSessionDelegate. */
        let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)

        /* Create the Request:
           My API (POST http://my-thermostat.dyndns.org:8083/get)
         */

        var URL = NSURL(string: "http://my-thermostat.dyndns.org:8083/get")
        let request = NSMutableURLRequest(URL: URL!)
        request.HTTPMethod = "POST"

        // Headers

        request.addValue("Basic dXNlcjpwYXNzd29yZA==", forHTTPHeaderField: "Authorization")

        // Form URL-Encoded Body

        let bodyParameters = [
            "OID4.3.2.3": "",
        ]
        let bodyString = self.stringFromQueryParameters(bodyParameters)
        request.HTTPBody = bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)

        /* Start a new Task */
        let task = session.dataTaskWithRequest(request, completionHandler: { (data : NSData!, response : NSURLResponse!, error : NSError!) -> Void in
            if (error == nil) {
                // Success
                let statusCode = (response as NSHTTPURLResponse).statusCode
                println("URL Session Task Succeeded: HTTP \(statusCode)")
            }
            else {
                // Failure
                println("URL Session Task Failed: %@", error.localizedDescription);
            }
        })
        task.resume()
    }

    /**
     This creates a new query parameters string from the given NSDictionary. For
     example, if the input is @{@"day":@"Tuesday", @"month":@"January"}, the output
     string will be @"day=Tuesday&month=January".
     @param queryParameters The input dictionary.
     @return The created parameters string.
    */
    func stringFromQueryParameters(queryParameters : Dictionary<String, String>) -> String {
        var parts: [String] = []
        for (name, value) in queryParameters {
            var part = NSString(format: "%@=%@",
                name.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!,
                value.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)
            parts.append(part)
        }
        return "&".join(parts)
    }

    /**
     Creates a new URL by adding the given query parameters.
     @param URL The input URL.
     @param queryParameters The query parameter dictionary to add.
     @return A new NSURL.
    */
    func NSURLByAppendingQueryParameters(URL : NSURL!, queryParameters : Dictionary<String, String>) -> NSURL {
        let URLString : NSString = NSString(format: "%@?%@", URL.absoluteString!, self.stringFromQueryParameters(queryParameters))
        return NSURL(string: URLString)!
    }
}

I assume I need the following above this code in Playground to work properly?

import Foundation
import XCPlayground

Last, the HTTP Post I used to convert was from the following and Paw converted this to NSURLSession above.

POST /get HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==
Content-Type: application/x-www-form-urlencoded
Host: my-thermostat.dyndns.org:8083
Connection: close
User-Agent: Paw/2.2.2 (Macintosh; OS X/10.10.4) GCDHTTPRequest
Content-Length: 11

OID4.3.2.3=

Thank you for your help!

1

There are 1 answers

9
pbodsk On BEST ANSWER

If I create a playground with your code I get three errors.

One in the function sendRequest() where you must change this line:

let statusCode = (response as NSHTTPURLResponse).statusCode

to

let statusCode = (response as! NSHTTPURLResponse).statusCode

(as! instead of as)

One in the function stringFromQueryParameters where you must change the following line

parts.append(part)

to

parts.append(part as String)

(add as String)

And one in the function NSURLByAppendingQueryParameters where you must change this:

return NSURL(string: URLString)!

to this:

return NSURL(string: URLString as String)!

(add as String)

And then the compiler seems satisfied...at least on my machine :-)

And yes, you need to import Foundation and XCPlayground as you figured out already.

Furthermore, if you need to make asynchronous calls...as is the case here, you'll need this method in the top of your code:

XCPSetExecutionShouldContinueIndefinitely()

(you can read more about it here)

And finally, to actually see your code run, you can add this to the bottom of your code, after the class definition:

let requestController = MyRequestController()
requestController.sendRequest()

Here is the complete code

import Foundation
import XCPlayground

XCPSetExecutionShouldContinueIndefinitely()

class MyRequestController {
    func sendRequest() {
        /* Configure session, choose between:
        * defaultSessionConfiguration
        * ephemeralSessionConfiguration
        * backgroundSessionConfigurationWithIdentifier:
        And set session-wide properties, such as: HTTPAdditionalHeaders,
        HTTPCookieAcceptPolicy, requestCachePolicy or timeoutIntervalForRequest.
        */
        let sessionConfig =   NSURLSessionConfiguration.defaultSessionConfiguration()

        /* Create session, and optionally set a NSURLSessionDelegate. */
        let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)

        /* Create the Request:
        My API (POST http://my-thermostat.dyndns.org:8083/get)
        */

        var URL = NSURL(string: "http://my-thermostat.dyndns.org:8083/get")
        let request = NSMutableURLRequest(URL: URL!)
        request.HTTPMethod = "POST"

       // Headers

        request.addValue("Basic dXNlcjpwYXNzd29yZA==", forHTTPHeaderField: "Authorization")

        // Form URL-Encoded Body

        let bodyParameters = [
            "OID4.3.2.3": "",
         ]
        let bodyString = self.stringFromQueryParameters(bodyParameters)
        request.HTTPBody = bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)

        /* Start a new Task */
        let task = session.dataTaskWithRequest(request, completionHandler: { (data : NSData!, response : NSURLResponse!, error : NSError!) -> Void in
            if (error == nil) {
                // Success
                let statusCode = (response as! NSHTTPURLResponse).statusCode
                println("URL Session Task Succeeded: HTTP \(statusCode)")
            }
            else {
                // Failure
                println("URL Session Task Failed: %@", error.localizedDescription);
            }
        })
        task.resume()
    }

    /**
    This creates a new query parameters string from the given NSDictionary. For
    example, if the input is @{@"day":@"Tuesday", @"month":@"January"}, the output
    string will be @"day=Tuesday&month=January".
    @param queryParameters The input dictionary.
    @return The created parameters string.
    */
    func stringFromQueryParameters(queryParameters : Dictionary<String, String>) -> String {
        var parts: [String] = []
        for (name, value) in queryParameters {
            var part = NSString(format: "%@=%@",
               name.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!,
            value.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)
            parts.append(part as String)
        }
        return "&".join(parts)
    }

    /**
    Creates a new URL by adding the given query parameters.
    @param URL The input URL.
    @param queryParameters The query parameter dictionary to add.
    @return A new NSURL.
    */
    func NSURLByAppendingQueryParameters(URL : NSURL!, queryParameters : Dictionary<String, String>) -> NSURL {
        let URLString : NSString = NSString(format: "%@?%@", URL.absoluteString!, self.stringFromQueryParameters(queryParameters))
       return NSURL(string: URLString as String)!
    }
}

let requestController = MyRequestController()
requestController.sendRequest()

Hope this helps