Last active
September 6, 2021 13:33
-
-
Save s4cha/6abd58a7ab5b22e7eea7b260c2f5a3db to your computer and use it in GitHub Desktop.
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
// MARK - Network Layer | |
// Repository implementation | |
// (here in an extension) | |
extension RestApi: OrganizationRepository { | |
public func fetchCurrent() -> AnyPublisher<Organization, Error> { | |
get("/organizations/current").map { (jsonOrganization: JSONOrganization) in | |
return jsonOrganization.toOrganization() | |
} | |
.eraseToAnyPublisher() | |
} | |
} | |
// JSON Parsing object | |
struct JSONOrganization: Decodable { | |
struct JSONOrganizationFeatureFlags: Decodable { | |
let is_chat_enabled: Bool | |
} | |
let name: String | |
let feature_flags: JSONOrganizationFeatureFlags | |
} | |
// JSON to Model bridge | |
extension JSONOrganization { | |
func toOrganization() -> Organization { | |
return Organization(name: name, isChatEnabled: feature_flags.is_chat_enabled) | |
} | |
} | |
// MARK - Domain Layer | |
// Domain Object | |
public struct Organization { | |
public let name: String | |
public let isChatEnabled: Bool | |
} | |
// Repository | |
public protocol OrganizationRepository { | |
func fetchCurrent() -> AnyPublisher<Organization, Error> | |
} | |
// ViewModel | |
public class OrganizationViewModel: ObservableObject { | |
@Inject private var repository: OrganizationRepository | |
// + VM logic | |
} | |
// View | |
public struct OrganizationView: View { | |
@StateObject var viewModel = OrganizationViewModel() | |
public var body: some View { | |
//... | |
} | |
} | |
// MARK - INJECTION (on app start) | |
let restApi = RestApi() | |
DependencyContainer.register(dependency: restApi as OrganizationRepository) | |
// MARK - Helper | |
/// Simple Dependency Injection with property wrapper @Inject | |
struct DependencyContainer { | |
private static var dependencies: [String:Any] = [:] | |
static func register<T>(dependency: T) { | |
dependencies[String(describing: T.self)] = dependency | |
} | |
static func resolve<T>() -> T { | |
guard let t = dependencies[String(describing: T.self)] as? T else { | |
fatalError("No povider registered for type \(T.self)") | |
} | |
return t | |
} | |
} | |
@propertyWrapper struct Inject<T> { | |
var wrappedValue: T | |
init() { | |
self.wrappedValue = DependencyContainer.resolve() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment