Skip to content

Instantly share code, notes, and snippets.

@jegnux
Created January 24, 2023 09:08
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 jegnux/103b68804d0044beecd56f08a68204e3 to your computer and use it in GitHub Desktop.
Save jegnux/103b68804d0044beecd56f08a68204e3 to your computer and use it in GitHub Desktop.
import Foundation
import SwiftUI
public struct DependencyBag<Dependency, Content: View> : View {
public init(
dependencyFactory: @escaping () -> Dependency,
@ViewBuilder view contentFactory: @escaping (Dependency) -> Content
) {
self.dependencyFactory = dependencyFactory
self.contentFactory = contentFactory
}
@State fileprivate var bag = Bag<Dependency>()
private let dependencyFactory: () -> Dependency
private let contentFactory: (Dependency) -> Content
public var body: some View {
contentFactory(bag.getOrMake(using: dependencyFactory))
}
}
private final class Bag<Dependency> {
private var dependency: Dependency?
func getOrMake(using factory: () -> Dependency) -> Dependency {
if let dependency {
return dependency
} else {
dependency = factory()
return dependency!
}
}
}
@jegnux
Copy link
Author

jegnux commented Jan 24, 2023

Example:

struct ItemList: View {

    @ObservedObject viewModel: ItemListViewModel

    var body: some View {
        List(items) { item in 
            NavigationLink {
                DependencyBag {
                    ItemDetailViewModel(item: item, api: viewModel.api)
                } view: { viewModel in 
                    ItemDetailView(viewModel: viewModel)
                }
            } label: {
                Text(item.title)
            }
        }
    }
}

struct ItemDetailView: View {

    @ObservedObject viewModel: ItemDetailViewModel

    var body: some View {
        // ...
    }
}

final class ItemDetailViewModel: ObservableObject {
    let item: Item
    let api: APIClient

    init(item: Item, api: APIClient) {
        self.item = item
        self.api = api
    }

    // ...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment