Created
September 14, 2017 21:37
-
-
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"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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