I'm providing an extremely simplified example to illustrate my point:
- A single SwiftUI
Viewdisplaying the same properties of aViewModel - 2
ViewModels which areObservableObjectsubclasses - The ViewModels have exactly the same properties, just the title/subtitle that are different and the underlying method calls that are different
How to correctly initialize a View so that it would "own" the ViewModel?
Normally I go about this as follows:
struct OverrideView: View {
@Environment(\.dismiss) private var dismiss
@StateObject private var viewModel: OverrideViewModelProtocol
init(_ viewModel: @escaping @autoclosure () -> OverrideViewModelProtocol) {
self._viewModel = StateObject(wrappedValue: viewModel())
}
var body: some View {
}
}
However, obviously this doesn't work since I cannot initialize a non-concrete class, the init is expecting some sort of some OverrideViewModelProtocol:
protocol OverrideViewModelProtocol: ObservableObject {
var mainTitle: String { get }
var overrideSelectedSegmentIndex: Int { get set }
var overrideCommentHeader: String { get }
var overrideComment: String { get set }
var overrideSubmitButtonEnabled: Bool { get }
var overrideShouldDismiss: Bool { get }
func submitButtonPressed()
}
Obviously, I cannot impose that the OverrideViewModelProtocol is also an ObservableObject, therefore I'm getting an issue:
Type 'any OverrideViewModelProtocol' cannot conform to 'ObservableObject'
One way to solve the problem is to create an abstract base class and use it instead of the protocol. But is there a way to use just the protocol and restrict only ObservableObject subclass to be able to conform to it, so that the View would know that it's a concrete ObservableObject subclass on initialization?
Use-case: 2 slightly different views, which differ only in text / button titles, so that I could use 2 different view models instead of if/else statements inside the views.
stateObjectis also a possibility in SwiftUI.