How to pass Published as Binding?
I have rating views for an array of products and a clear button, when the clear button is pressed I want to clear the ratings of all.
I am converting the Published object to Binding in order to reflects the updates but it doesn't work.
If I use direct $viewModel.products
in ForEach the ratings update & clear works perfectly.
struct ProductModel: Identifiable, Equatable {
var id: Int
var title: String
var rating: Int
mutating func clearRating() {
rating = 0
}
}
protocol ViewModelType: ObservableObject {
associatedtype Input
associatedtype State
var state: State { get }
func trigger(_ input: Input)
var subscriptions: Set<AnyCancellable> { get }
}
struct TestView: View {
@StateObject var viewModel = TestViewModel()
var body: some View {
switch viewModel.state {
case .initial:
Text("Hello world")
.onAppear {
viewModel.trigger(.initial)
}
case .data(let products):
VStack(spacing: 20) {
ForEach(products) { product in
Text("\(product.rating.wrappedValue)")
RatingStarView(rating: product.rating)
}
Button {
viewModel.clear()
} label: {
Text("Clear Rating")
}
}
}
}
}
class TestViewModel: ViewModelType {
enum State {
case initial
case data(Binding<[ProductModel]>)
}
enum Input {
case initial
case clear
}
@Published var state: State = .initial
@Published var products: [ProductModel] = [.init(id: 101, title: "Product 1", rating: 3),
.init(id: 102, title: "Product 2", rating: 2)]
func trigger(_ input: Input) {
switch input {
case .initial:
convertPublishedToBinding()
case .clear:
clear()
}
}
func clear() {
products.indices.forEach { products[$0].clearRating() }
}
private func convertPublishedToBinding() {
state = .data(Binding(get: { [weak self] in
self?.products ?? []
}, set: { [weak self] newValue in
print(newValue)
self?.products = newValue
}))
}
}
NOTE: I was referring to this article https://quickbirdstudios.com/blog/swiftui-architecture-redux-mvvm/