On 27 Oct 2016, at 13:01, Steven Harms via swift-users <swift-users@swift.org> 
wrote:

> At this point I'm going to have to confess that I need some help clarifying 
> my model.

Quite.  There two real issues here:

* You don’t need to create a queue just to start a request.  It’s fine to start 
the request from any context.  Thus, your `queue.async(…)` call is not needed.

* URLSession will run requests asynchronously, thus you need to prevent your 
process from terminating until the relevant requests are done.  In a real 
program the framework you’re using typically does this for you.  In a test 
project like this you have two options:

- dispatchMain() — That is, just add a line containing `dispatchMain()` to the 
bottom of your ‘main’ code.

- synthetic synchronous — Traditionally this is done using dispatch semaphores; 
I won’t show it here because a) you’ll find lots of example of it, and b) it’s 
not recommended, for obscure reasons related to QoS propagation.

> 1. How did point "y" get fired twice? Or how did it happen not at all?

I ran your code verbatim (except that I added a `dispatchMain()` at the end) on 
my Mac running 10.11.6, built with Xcode 8, and I didn’t see the second copy of 
`y`.

> 2. How did my callback for dataTask *never* fire? Even if the connection task 
> *failed* the handler ought have fired, no?

Because the process terminated before the request finished.

> 3. I didn't want to bring this whole queue business into the picture, but it 
> appears that without it the program exits before the handler has a chance to 
> fire.

Correct.

> 4. Changing to a queue.sync from queue.async consistently produces the output 
> I expect, but does not fire my completionHandler still.

Right, because that’s about how the request /starts/, not about how the 
request’s completion handler runs.

> 5. Is there a canonical reference for doing this simplest of tasks?

Here’s a minimal example of a command line tool that fetches a URL.

---------------------------------------------------------------------------
import Foundation

URLSession.shared.dataTask(with: URL(string: "http://www.example.com";)!) { 
(data, response, error) in
    if let error = error {
        print("error: \(error)")
        exit(1)
    } else {
        let response = response as! HTTPURLResponse
        let data = data!
        print("status: \(response.statusCode)")
        for (key, value) in response.allHeaderFields {
            print("header: \(key) = \(value)")
        }
        print("body: \(data as NSData)")
        exit(0)
    }
}.resume()
dispatchMain()
---------------------------------------------------------------------------

When I run this (same environment as above) I get this:

status: 200
header: Date = Fri, 28 Oct 2016 08:02:04 GMT
header: Content-Length = 606
header: Etag = "359670651"
header: x-ec-custom-error = 1
header: Last-Modified = Fri, 09 Aug 2013 23:54:35 GMT
header: Accept-Ranges = bytes
header: Vary = Accept-Encoding
header: X-Cache = HIT
header: Content-Type = text/html
header: Expires = Fri, 04 Nov 2016 08:02:04 GMT
header: Server = ECS (ewr/15BD)
header: Content-Encoding = gzip
header: Cache-Control = max-age=604800
body: <3c21646f 63747970 65206874 6d6c3e0a 3c68746d …>

The only weird thing in the code above is that `key` is of type `AnyHashable` 
rather than `String`.  That’s because the type of `allHeaderFields` is wrong    
  <rdar://problem/27805863>.

Alas, I’m not set up to run this on Linux )-:

Share and Enjoy 
--
Quinn "The Eskimo!"                    <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware


_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to