Skip to content

Instantly share code, notes, and snippets.

@sharplet
Created September 14, 2017 21:37
  • Star 17 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save sharplet/37210c02aa9e525b55f823bb67712725 to your computer and use it in GitHub Desktop.
Example Source Code for "A Simple Approach to Thread-Safe Networking in iOS Apps"
import Foundation
import PlaygroundSupport
enum URLResult {
case response(Data, URLResponse)
case error(Error, Data?, URLResponse?)
}
extension URLSession {
@discardableResult
func get(_ url: URL, completionHandler: @escaping (URLResult) -> Void) -> URLSessionDataTask {
let task = dataTask(with: url) { data, response, error in
switch (data, response, error) {
case let (data, response, error?):
completionHandler(.error(error, data, response))
case let (data?, response?, nil):
completionHandler(.response(data, response))
default:
preconditionFailure("expected either Data and URLResponse, or Error")
}
}
task.resume()
return task
}
@discardableResult
func get(_ left: URL, _ right: URL, completionHandler: @escaping (URLResult, URLResult) -> Void) -> (URLSessionDataTask, URLSessionDataTask) {
precondition(delegateQueue.maxConcurrentOperationCount == 1,
"URLSession's delegateQueue must be configured with a maxConcurrentOperationCount of 1.")
var results: (left: URLResult?, right: URLResult?) = (nil, nil)
func continuation() {
guard case let (left?, right?) = results else { return }
completionHandler(left, right)
}
let left = get(left) { result in
results.left = result
continuation()
}
let right = get(right) { result in
results.right = result
continuation()
}
return (left, right)
}
}
extension URLResult {
var string: String? {
guard case let .response(data, _) = self,
let string = String(data: data, encoding: .utf8)
else { return nil }
return string
}
}
let zen = URL(string: "https://api.github.com/zen")!
URLSession.shared.get(zen, zen) { left, right in
guard case let (quote1?, quote2?) = (left.string, right.string)
else { return }
print(quote1, quote2, separator: "\n")
// Approachable is better than simple.
// Practicality beats purity.
}
PlaygroundPage.current.needsIndefiniteExecution = true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment