During the development of our new SwiftUI apps we found issues while trying to implement well-known patterns such as MVVM. Searching online is tough because blogs can state different answers for the same problem, and Apple hasn't been very clear about this in the documentation.
Requirements:
- Ensure single initialization
- If not properly used, the framework might lead you to accidentally make the View reinstantiate the ViewModel during its execution
- Initialization parameters
- We sometimes need to provide the ViewModel with parameters for initialization in the following data flow pattern:
parentView.body -> childView.init(params) -> childViewModel.init(params)
- We sometimes need to provide the ViewModel with parameters for initialization in the following data flow pattern:
- Testing
- We also want to be able to provide a completely different ViewModel to the view in case we're testing it, this should be possible if the mocked VM follows the same protocol of the normal VM
Our current solution doesn't meet all requirements yet:
struct ParentView: View {
var body: some View {
ChildView(someValue: "foo")
}
}
class ChildViewModel: ObservableObject {
init(someValue: Any) {
}
}
struct ChildView: View {
@StateObject var vm: ChildViewModel
init(someValue: Any) {
self._vm = StateObject(wrappedValue: .init(someValue: someValue)
}
}
Is there an example project that implements some or even all of the above requirements, while meeting Apple's guidelines and best practices? Does our current solution have any immediately noticeable mistakes?
Thanks in advance.