Skip to content

Instantly share code, notes, and snippets.

@angelinaFri
Created June 17, 2020 18:25
Show Gist options
  • Save angelinaFri/021ff8a24d91c2f16dd77688feec568f to your computer and use it in GitHub Desktop.
Save angelinaFri/021ff8a24d91c2f16dd77688feec568f to your computer and use it in GitHub Desktop.
Populating UI from Multiple Services
struct Article {}
struct Picture {}
typealias ArticleLoaderResult = Swift.Result<[Article], Error>
protocol ArticleLoader {
func load(date: Date, completion: @escaping (ArticleLoaderResult) -> Void)
}
typealias PictureLoaderResult = Swift.Result<[Picture], Error>
protocol PictureLoader {
func load(date: Date, completion: @escaping (PictureLoaderResult) -> Void)
}
typealias DailyLoaderResult = Swift.Result<String, Error>
protocol DailyLoader {
func load(completion: @escaping (DailyLoaderResult) -> Void)
}
struct MainModel {
let articles: [Article]
let pictures: [Picture]
let dailyQuote: String
}
protocol MainLoader {
typealias Result = Swift.Result<MainModel, Error>
func load(date: Date, completion: @escaping (Result) -> Void)
}
class MainLoaderAdapter: MainLoader {
let articleLoader: ArticleLoader
let pictureLoader: PictureLoader
let dailyLoader: DailyLoader
private let queue = DispatchQueue(label: "MainLoaderAdapter.queue")
init(articleLoader: ArticleLoader, pictureLoader: PictureLoader, dailyLoader: DailyLoader) {
self.articleLoader = articleLoader
self.pictureLoader = pictureLoader
self.dailyLoader = dailyLoader
}
private struct PartialResult {
var articles: [Article]? {
didSet { checkCompletion() }
}
var pictures: [Picture]? {
didSet { checkCompletion() }
}
var dailyQoute: String? {
didSet { checkCompletion() }
}
var error: Error? {
didSet { checkCompletion() }
}
var completion: ((MainLoader.Result) -> Void)?
private mutating func checkCompletion() {
if let error = error {
completion?(.failure(error))
} else if let articles = articles, let pictures = pictures, let dailyQuote = dailyQoute {
completion?(.success(MainModel(
articles: articles,
pictures: pictures,
dailyQuote: dailyQuote)))
completion = nil
}
}
}
func load(date: Date, completion: @escaping (MainLoader.Result) -> Void) {
var partialResult = PartialResult(completion: completion)
articleLoader.load(date: date) { articleResult in
self.queue.sync {
switch articleResult {
case let .failure(error):
partialResult.error = error
case let .success(value):
partialResult.articles = value
}
}
}
pictureLoader.load(date: date) { pictureResult in
self.queue.sync {
switch pictureResult {
case let .failure(error):
partialResult.error = error
case let .success(value):
partialResult.pictures = value
}
}
}
dailyLoader.load { dailyResult in
self.queue.sync {
switch dailyResult {
case let .failure(error):
partialResult.error = error
case let .success(value):
partialResult.dailyQoute = value
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment