Last active
June 30, 2019 11:39
-
-
Save szotp/84b6e48a2c35cab51783a5c0bc4ca2ef to your computer and use it in GitHub Desktop.
Handling result with less completion calls
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
// | |
// main.swift | |
// Completions | |
// | |
// Created by szotp on 30/06/2019. | |
// Copyright © 2019 szotp. All rights reserved. | |
// | |
import Foundation | |
typealias CompletionBlock = Optional<() -> Void> | |
func apiRequest(input: Int, onSuccess: (String) -> Void, onFailure: (Error) -> Void) { | |
onSuccess("") | |
} | |
func apiRequestWrapped(completion: CompletionBlock) { | |
let cmpl = Completor<String>(completion) { result in | |
let data = try result.get() | |
print(data) | |
} | |
if (arc4random() % 2) == 0 { | |
apiRequest(input: 5, onSuccess: cmpl.onSuccess, onFailure: cmpl.onFailure) | |
} else { | |
// cmpl.deinit will be called and complete automatically | |
} | |
} | |
class Completor<T> { | |
typealias ResultCallback = (Result<T, Error>) throws -> Void | |
private var didComplete = false | |
private var completion: CompletionBlock | |
private var onResult: ResultCallback | |
init(_ completion: CompletionBlock, onResult: @escaping ResultCallback) { | |
self.completion = completion | |
self.onResult = onResult | |
} | |
func onSuccess(value: T) { | |
complete(.success(value)) | |
} | |
func onFailure(error: Error) { | |
print(error) | |
complete(.failure(error)) | |
} | |
func complete(_ result: Result<T, Error>?) { | |
assert(!didComplete) | |
if let result = result { | |
do { | |
try onResult(result) | |
} catch let error { | |
// apply default behavior here, show toast or something, depends on the app | |
print(error) | |
} | |
} | |
let completion = self.completion | |
DispatchQueue.main.async { | |
let desc = result.map { "\($0)"} ?? "nil" | |
print("completion with \(desc)") | |
completion?() | |
} | |
didComplete = true | |
} | |
deinit { | |
if !didComplete { | |
complete(nil) | |
} | |
} | |
} | |
apiRequestWrapped { | |
print("ok") | |
} | |
RunLoop.main.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment