Skip to content

Instantly share code, notes, and snippets.

@andreacipriani
Last active August 7, 2017 09:24
Show Gist options
  • Save andreacipriani/574fa2975c14b0e5c8b53ff628418c31 to your computer and use it in GitHub Desktop.
Save andreacipriani/574fa2975c14b0e5c8b53ff628418c31 to your computer and use it in GitHub Desktop.
import Foundation
// Models:
struct TrackModel {
let title: String
}
struct UserModel {
let name: String
}
struct PlaylistModel {
let genre: String
}
enum RepositoryData {
case tracks([TrackModel])
case users([UserModel])
case playlists([PlaylistModel])
}
// Interfaces:
enum Result<RepositoryData,Error> {
case success(RepositoryData)
case failure(Error)
}
protocol Fetching {
func fetch(completion: @escaping ((Result<RepositoryData, Error>) -> ()))
}
protocol RepositoryChaining: Fetching {
var next: RepositoryChaining? { get }
}
class RepositoryChain: RepositoryChaining {
let fetcher: Fetching
var next: RepositoryChaining?
init(fetcher: Fetching, next: RepositoryChaining? = nil) {
self.fetcher = fetcher
self.next = next
}
func fetch(completion: @escaping ((Result<RepositoryData, Error>) -> ())) {
fetcher.fetch { result in
switch result {
case .success(let entity):
//execute success operation?
completion(.success(entity))
case .failure(let error):
//execute failure operation?
if self.next != nil {
self.next?.fetch(completion: completion)
} else {
completion(.failure(error))
}
}
}
}
}
// Fetchers:
class CoreDataFetcher: Fetching {
let failing: Bool
init(failing: Bool = false) {
self.failing = failing
}
func fetch(completion: @escaping ((Result<RepositoryData, Error>) -> ())) {
let tracks = [TrackModel(title: "track from core data")]
failing ? completion(.failure(NSError())) : completion(.success(.tracks(tracks)))
}
}
class NetworkFetcher: Fetching {
let failing: Bool
init(failing: Bool = false) {
self.failing = failing
}
func fetch(completion: @escaping ((Result<RepositoryData, Error>) -> ())) {
let tracks = [TrackModel(title: "track from the network")]
failing ? completion(.failure(NSError())) : completion(.success(.tracks(tracks)))
}
}
class RepositoryFactory {
static func makeCoreDataNewtworkRepo() -> Fetching {
let networkRepo = RepositoryChain(fetcher: NetworkFetcher())
return RepositoryChain(fetcher: CoreDataFetcher(failing: true), next: networkRepo)
}
}
// Example:
let coreDataNewtorkRepo = RepositoryFactory.makeCoreDataNewtworkRepo()
coreDataNewtorkRepo.fetch { result in
print(result)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment