0

I'm new on iOS development, I was following this tutorial: https://grokswift.com/simple-rest-with-swift/ and I don't know why the following code always return "the placeholder" and I can't see errors on the console's output:

import Foundation

class Resolver{
    func doSomething() -> String{
        var result = "the placeholder"
        print("inside doSomething")
        let postEndpoint: String = "http://jsonplaceholder.typicode.com/posts/1"
        guard let url = NSURL(string: postEndpoint) else {
            print("Error: cannot create URL")
            return "error here"
        }

        let urlRequest = NSURLRequest(URL: url)

        let config = NSURLSessionConfiguration.defaultSessionConfiguration()

        let session = NSURLSession(configuration: config)
         print("another thing")

        let task = session.dataTaskWithRequest(urlRequest, completionHandler: {
            (data, response, error) in
            guard let responseData = data else {
                print("Error: did not receive data")
                return
                //return "error here"
            }
            print("hereeeeeee ############")
            guard error == nil else {
                print("error calling GET on /posts/1")
                print(error)
                return
                //return "error here"
            }
            // parse the result as JSON, since that's what the API provides
            let post: NSDictionary
            do {
                post = try NSJSONSerialization.JSONObjectWithData(responseData,
                    options: []) as! NSDictionary
            } catch  {
                print("error trying to convert data to JSON")
                return
                //return "error here"
            }
            // now we have the post, let's just print it to prove we can access it
            print("The post is: " + post.description)
            result = post.description

            // the post object is a dictionary
            // so we just access the title using the "title" key
            // so check for a title and print it if we have one
            if let postTitle = post["title"] as? String {
                print("The title is: " + postTitle)
            }

        })
        task.resume()

        return result
    }    

}

this is my info.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleIdentifier</key>
    <string></string>
    <key>CFBundleExecutable</key>
    <string></string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>LSApplicationCategoryType</key>
    <string></string>
    <key>CFBundleName</key>
    <string></string>
    <key>CFBundleDisplayName</key>
    <string></string>
    <key>CFBundleVersion</key>
    <string></string>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSExceptionDomains</key>
        <dict>
            <key>httpbin.org</key>
            <dict>
                <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
            <key>jsonplaceholder.typicode.com </key>
            <dict>
                <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>
    <key>CFBundleShortVersionString</key>
    <string></string>
    <key>CFBundleGetInfoString</key>
    <string></string>
</dict>
</plist>

When I run the test I see this output:

Test Suite 'RestTest' started at 2016-03-03 15:38:49.364
Test Case '-[FoodTrackerTests.RestTest testResolver]' started.
inside doSomething
another thing
// I want to see the result: the placeholder
Test Case '-[FoodTrackerTests.RestTest testResolver]' passed (0.061 seconds).
Test Suite 'RestTest' passed at 2016-03-03 15:38:49.425.
     Executed 1 test, with 0 failures (0 unexpected) in 0.061 (0.062) seconds
Test Suite 'Selected tests' passed at 2016-03-03 15:38:49.426.
     Executed 1 test, with 0 failures (0 unexpected) in 0.061 (0.063) seconds

Why the result variable doesn't contains the post.description value?

brandonscript
  • 68,675
  • 32
  • 163
  • 220
Pedro Hidalgo
  • 861
  • 10
  • 15
  • Have you tried adding breakpoints inside `task`? Why does that never get called? Your errors also aren't throwing. Perhaps this is because you're running tests and the tests complete before the asynchronous API call does? – brandonscript Mar 03 '16 at 20:09
  • I tried running your code in a playground and it does not produce output, just as you found. But when I ran it on a real machine, it worked fine, straight away. – emrys57 Mar 03 '16 at 20:40
  • @remus you were right. The tests always finish before the http call completes. I don't know if you have to post the answer to mark it as accepted or if I have to do that myself. – Pedro Hidalgo Mar 03 '16 at 21:43

2 Answers2

0

The doSomething() method returns "the placeholder" value before the asynchronous call is finished. That's why you see it.

Rafał Sroka
  • 39,540
  • 23
  • 113
  • 143
0

As suggested in the comments, it looks like tests are completing before the HTTP call is returned (because the HTTP request is asynchronous) and thus you aren't seeing the results of the API call before the test run ends.

Have a look at XCAsyncTestCase and set up your tests to wait for the async callback instead.

Community
  • 1
  • 1
brandonscript
  • 68,675
  • 32
  • 163
  • 220