I’ve created a protocol as follows:
protocol InputViewModel: ObservableObject, Identifiable {
var id: UUID { get }
var title: String { get }
var shouldShowTitle: Bool { get }
var data: String { get set }
var placeholder: String { get }
var fieldType: FieldType { get }
}
Using this protocol, I’ve created types like TextFieldViewModel
, TextViewViewModel
, DatePickerViewModel
etc
In my SwiftUI view, I have a list which could have any input type so I have an array as follows:
private(set) var inputViewModels: [any InputViewModel] = []
I populate this with required view models.
Now in my SwiftUI view, I want to loop through these view models and build the UI so I do this:
List {
ForEach(currentProjectViewModel.projectInfoViewModels) { inputViewModel in
if let inputViewModel = inputViewModel as? TextFieldRowViewModel {
createUI(inputViewModel: inputViewModel)
}
}
}
This is where I get the error Type 'any InputViewModel' cannot conform to 'Identifiable'
I know one way to fix this would be to make the inputViewModels
of a specific type so that would be private(set) var inputViewModels: [InputViewModel] = []
without the use of any
, however, I do have the requirement to support any input type.
Another solution would be to use indices
as follows
ForEach(currentProjectViewModel.projectInfoViewModels.indices, id: \.self) { index in
let viewModel = currentProjectViewModel.projectInfoViewModels[index]
if let inputViewModel = viewModel as? TextFieldRowViewModel {
createUI(inputViewModel: inputViewModel)
}
}
However, I’ve heard that using indices is not really reliable in SwiftUI views and as much as possible we want to iterate over the object
I also came across this answer but it is similar to the first solution I pointed out here.
How could I achieve what I want in the simplest / cleanest way possible ?