SwiftUI & MVVM: How to animate "list elements change" when view model changes the "data source" (`@Publish items`) itself

Viewed 341

I am still relatively new to SwfitUI and Combine so maybe I am trying to do something very incorrectly but I just cannot see how to achieve what I am aiming to do with SwiftUI and MVVM. Here is the scenario:

  • ViewModel class with a property @Published var items = [String]()
  • Main view (HomeView) that has a ForEach showing the items from its view model
  • HomeView has a @StateObject var viewModel: ViewModel
  • The HomeView ForEach uses the items from viewModel
  • ViewModel changes the items (in my case core data changes)
  • The HomeView ForEach reflects the change immediately

This all works, but what I want to do is animate the elements in the ForEach changing due to the viewModel.items changing.

What I can do is import SwiftUI into the ViewModel and use withAnimation to wrap the setting of new items. But this beats the purpose of the ViewModel as it now has a direct reference to UI code.

Here some code I have:

struct HomeView: View {
    @StateObject var viewModel: ViewModel

    var body: some View {
         ForEach(items) { item in
            Text(item)
        }
    }
}
import SwiftUI // This should not be imported as it breaks MVVM patter

class ViewModel {
    @Published var items = [String]()

    func onItemsChanged(_ newItems: [String]) {
       withAnimation { // This works but will break MVVM patter
          items = newItems
       }
    }
}

Any ideas if this can be achieve to make MVVM happy and work with SwiftUI?

1 Answers
Related