Dmitry Danilau
07/11/2024, 9:51 PMclass MyVm: ObservableObject {
@Published private(set) var state: ScreenState
func observeViewState() async {
for await kmpState in stateHolder.state {
let viewState = onEnum(of: kmpState)
// Update state here
}
}
}
data class ScreenState(
val value1: SomeClass1,
val value2: SomeClass2
)
My screen in SwiftUI uses properties to render different parts of the screen: value1
renders a list of items, and value2
renders a card.
As I understand it and what I see in the logs, if any property in the @Published
property changes, it causes the entire screen to re-render (both components). That is, if value1
changes, I expect the list of items to re-render, and the card should remain untouched since there were no changes.
So far, I see that for each property in the state, I need to create its own @Published
variable and pass it specifically to the component. This works on a simple screen, but if I have nested views and more than 3-5 such variables, to update a specific view in the hierarchy, I need to pass a specific @Published
variable that will control the re-rendering when the corresponding variable changes.
What is the preferable approach?
Ty in advanceAndrei Salavei
07/12/2024, 1:18 PMDmitry Danilau
07/12/2024, 1:19 PMDmitry Danilau
07/12/2024, 1:47 PMKMPState(
val user: User,
val habits: List<Habits>,
val address: List<Address>
)
data class User(id,name, password)
data class Habits(id, name, isActive)
data class Address(country, city, street)
VM
class iOSViewModel : ObservableObject {
@Published private(set) var user: User
@Published private(set) var habits: Habits
@Published private(set) var address: Address
func observeViewState() async {
for await kmpState in stateHolder.state {
let viewState = onEnum(of: kmpState)
// Assume we map to UI models
}
}
}
View
struct ScreenView: View {
@StateObject let viewModel = iOSViewModel.init()
val body: View {
VStack {
UserView(viewModel.user)
HabitsListView(viewModel.habits)
AddressListView(viewModel.address)
}
}
}
tyAndrei Salavei
07/12/2024, 2:02 PMclass ObservableWrapper<T>: ObservableObject {
@Published var value: T
}
class MyScreenViewModel {
let user: ObservableWrapper<User>
let habits: ObservableWrapper<Habits>
let address: ObservableWrapper<Address>
}
And here:
struct MyScreenView: View {
let viewModel: MyScreenViewModel // Should pass as a parameter
val body: View {
VStack {
UserView(viewModel.user)
HabitsListView(viewModel.habits)
AddressListView(viewModel.address)
}
}
}
And from the architecture perspective, it's better to have State
classes written in Swift.Dmitry Danilau
07/12/2024, 2:19 PM