SwiftUI viewModel with array of [any PROTOCOL] inside

99 Views Asked by At

I am trying to implement viewModel which contains an array with observable objects and everything is covered by interfaces. How can I achieve this? My code right now gives an error

Type 'any IItemViewModel' cannot conform to 'IItemViewModel'

protocol IItemViewModel: ObservableObject {
    var title: String { get }
}

final class ItemViewModel: IItemViewModel, ObservableObject {
    let title: String
    
    init(title: String) {
        self.title = title
    }
}

protocol IMainViewModel: ObservableObject {
    var list: [any IItemViewModel] { get }
}

final class MainViewModel: IMainViewModel {
    @Published var list = [any IItemViewModel]()
    
    required init() {
        list.append(ItemViewModel(title: "test1"))
    }
}

struct MainView<ViewModel>: View where ViewModel: MainViewModel  {
    @ObservedObject var viewModel: ViewModel
    var items = [any IItemViewModel]()
    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            LazyVStack(spacing: 0) {
                ForEach(viewModel.list, id: \.title) { model in
                    ItemView(viewModel: model) // <-- ERROR HERE
                }
            }
        }
    }
}

struct ItemView<ViewModel>: View where ViewModel: IItemViewModel {
    @ObservedObject var viewModel: ViewModel
    
    init(viewModel: ViewModel) {
        self.viewModel = viewModel
    }
    
    var body: some View {
        Text(viewModel.title)
    }
}
1

There are 1 best solutions below

2
malhal On

It's best to use the View protocol for your view model, e.g. for read only:

struct MainView: View  {
    let items: [Item]

    var body: some View {

or for read/write:

struct MainView: View  {
    @State var items: [Item] = []

    var body: some View {

or

struct MainView: View  {
    @Binding var items: [Item]

    var body: some View {