When should withDependencies(from: self)
be used?
#49
-
I initially understood that when a model creates a child model, I always need to wrap the initialization of the child model with
For instance, I have a following MWE: import Dependencies
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView(
viewModel: withDependencies {
let calendar = Calendar.current
let comps = DateComponents(calendar: calendar, year: 2000, month: 1, day: 1)
$0.date.now = calendar.date(from: comps)!
} operation: { ContentViewModel() }
)
}
}
}
final class ContentViewModel: ObservableObject {
private(set) var subviewModel: SubviewModel!
init() { /****** HERE ******/ subviewModel = withDependencies(from: self) { SubviewModel() } }
}
struct ContentView: View {
@ObservedObject private(set) var viewModel: ContentViewModel
var body: some View { Subview(viewModel: viewModel.subviewModel) }
}
final class SubviewModel: ObservableObject {
@Published private(set) var text: String = ""
@Dependency(\.date) var date
init() { text = date.now.formatted() }
}
struct Subview: View {
@ObservedObject private(set) var viewModel: SubviewModel
var body: some View { Text(viewModel.text) }
} I overrode However,
This is confusing because Indeed, I discovered that Why does the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hey @Zeta611. I agree that this can be a little confusing. Maybe some insight about the internals could make things clearer:
func onButtonTapped() {
self.childModel = withDependencies(from: self) {
ChildModel()
}
}
// or
func onButtonTapped() {
withDependencies(from: self) {
self.childModel = ChildModel()
}
} This is roughly equivalent to the pseudo-code: withDependencies {
let currentModelDependencies = extractCompleteDependencyValuesFrom@DependencyInSelf()
$0 = currentModelDependencies
} operation: {
self.childModel = ChildModel()
} In other words, you use I hope it makes things clearer. Let me know if it doesn't. |
Beta Was this translation helpful? Give feedback.
Hey @Zeta611. I agree that this can be a little confusing. Maybe some insight about the internals could make things clearer:
@Dependency
property wrapper is initialized, it internally captures the complete set of currentDependencyValues
, independently of theKeyPath
it observes. This is not a general property of property wrappers, but something that was implemented on purpose. When a model instance is initialized, all its@Dependency
property wrappers values (the_
values) are initialized.@Dependency
is able toinit
itself from theKeyPath
only, and that's why you don't need to pass a default value, and you don't see it, but it happens right before the model'sinit
.withDependen…