Skip to content

Instantly share code, notes, and snippets.

@s4cha
Last active September 6, 2021 13:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save s4cha/6abd58a7ab5b22e7eea7b260c2f5a3db to your computer and use it in GitHub Desktop.
Save s4cha/6abd58a7ab5b22e7eea7b260c2f5a3db to your computer and use it in GitHub Desktop.
// 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