1

I'm attempting to write a simple API client in Swift 2.2 using NSURLSession for a server I'm running locally at port 3000. The server just serves up a static string of JSON.

This works fine:

$ curl http://localhost:3000
{"data":"value"}

My Swift code to hit the API is:

// api_client.swift

let url = NSURL(string: "http://localhost:3000/api")

let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
    print("The response was:")
    print(NSString(data: data!, encoding: NSUTF8StringEncoding))
}

print("Running the request...")
task.resume()

I'm attempting to run it from the command line

$ swift api_client.swift
Running the request...

But that's all that happens. I don't see the "The response was" line printed, or the response from the server. When I check the server logs it shows no request came in at all.

What am I doing wrong? I'm very new to Swift and am having trouble figuring this out. I'm on Swift 2.2 and XCode 7.3

akowalz
  • 350
  • 3
  • 16
  • My guess is that this method is async and the runtime is reaching the end of your code before the method finishes executing so the completion is never called. – pbush25 Apr 02 '16 at 16:53
  • @pbush25 so how could I test this is the case and then fix it? What's a better way to run code like this? I don't want to go make a full-blow iOS app yet (although that's eventually the goal) just to get this piece working. – akowalz Apr 02 '16 at 17:07
  • If you run this code *from the command line* it won't work because in this case your app has no runloop. Have a look at this: http://stackoverflow.com/questions/30702387/using-nsurlsession-from-a-swift-command-line-program – Eric Aya Apr 02 '16 at 17:09
  • awesome! thank you! I actually managed to get a response from the server just by wrapping my request in `while true { task.resume() }`. Not very elegant but at least I know the request was made. Thanks for the help! – akowalz Apr 02 '16 at 17:12

2 Answers2

0

To follow up on what pbush25 said. Can you try to create a callback in your code?

func GET(path : String, callback: (result: NSData?, response: NSHTTPURLResponse?, error: NSError?) -> Void) {
    let session = NSURLSession.sharedSession()  
    let url = NSURL(string: path)  
    let task = session.dataTaskWithURL(url!){  
        (data, response, error) -> Void in  
            if (error != nil) {
                // return the NSData as nil (since you have an error)
                callback(result: nil, response: response as? NSHTTPURLResponse, error: error!)
            } else {
                // return the NSData
                callback(result: data, response: response as? NSHTTPURLResponse, error: nil)
            }
        }  
    task.resume()  
}

And then calling your function with:

GET("http://localhost:3000/api") {
    (data, response, error) -> Void in 
    print(data)
}
akowalz
  • 350
  • 3
  • 16
Emptyless
  • 2,658
  • 1
  • 15
  • 28
  • I had to edit the code for a few mistakes, but once I did and ran it, again, nothing happened at all. No request in my server logs. – akowalz Apr 02 '16 at 17:04
0

Thanks to pbush25 I figured out that my request wasn't executing because the runtime reached the end of the file before the async request kicked off.

Another user with this problem solved it using semaphores, but a quick and dirty way to prove this was the problem was by adding sleep(1) at the bottom of the code. If I do this, I see request in the logs and the data returned!

Community
  • 1
  • 1
akowalz
  • 350
  • 3
  • 16