Create a gist now

Instantly share code, notes, and snippets.

@erica /block.swift
Last active Apr 11, 2017

What would you like to do?
import Foundation
/// A generic Cocoa-Style completion handler
typealias CompletionHandler<T> = (T?, Error?) -> Void
/// A generic result type that returns a value or an error
enum Result<T> { case success(T), error(Error), uninitialized }
/// Provides syncronous access to results returned by
/// asynchronous processes with completion handlers
class SyncMaker<Value> {
var result: Result<Value> = .uninitialized
/// Generates a synchronous-compliant completion handler
func completion() -> CompletionHandler<Value> {
return {
(value: Value?, error: Error?) in
var result: Result<Value> = .uninitialized
// Fetch result
switch(value, error) {
case (let value?, _): result = .success(value)
case (_, let error?): result = .error(error)
default: break
}
// Store result, return control
self.result = result
CFRunLoopStop(CFRunLoopGetCurrent())
}
}
// Perform task (that must use custom completion handler) and wait
func run(_ task: @escaping () -> Void) -> Result<Value> {
task()
CFRunLoopRun()
return result
}
}
// Example of using SyncMaker
import CoreLocation
import Contacts
struct BadKarma: Error {}
func getCityState(from zip: String) throws -> String {
let geoCoder = CLGeocoder()
let infoDict = [
CNPostalAddressPostalCodeKey: zip,
CNPostalAddressISOCountryCodeKey: "US"]
let syncMaker = SyncMaker<[CLPlacemark]>()
let result = syncMaker.run {
geoCoder.geocodeAddressDictionary(
infoDict,
completionHandler: syncMaker.completion())
}
switch result {
case .error(let complaint): throw(complaint)
case .success(let placemarks):
guard placemarks.count > 0 else { break }
let mark = placemarks[0]
guard let address = mark.addressDictionary,
let city = address["City"],
let state = address["State"]
else { break }
return "\(city), \(state)"
default: break
}
throw BadKarma()
}
do {
for zip in ["10001", "20500", "999999"] {
print("zip: \(zip), citystate:", try getCityState(from: zip))
}
} catch { print(error) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment