Hello everyone,
Please find the below test code.
My issue is that the MyPickerView
from ContentView
body can be used, while the one from sheet cannot be used because its selection resets when counter
value changes, which triggeres UI to be re-rendered, so my views to be reinitialised.
This is my ViewModel
which holds a counter which is increased by a Timer publisher located in ContentView
.
class ViewModel: ObservableObject {
@Published var counter: Int = 0
}
Here in ContentView
, the MyPickerView
located in the VStack
can be used without any issue while updating the counter
, even if MyPickerView
is getting reinitialised on every counter
update.
struct ContentView: View {
@StateObject private var vm: ViewModel = ViewModel()
@State private var pickerSelection: Int = 0
@State private var showSheet: Bool = false
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
init() {
print("ContentView init")
}
var body: some View {
VStack {
FrequentlyUpdatedView(counter: $vm.counter)
.onReceive(timer) { _ in
self.vm.counter += 1
}
MyPickerView(selection: $pickerSelection)
Button {
showSheet.toggle()
} label: {
Text("Show Sheet")
}
}
.sheet(isPresented: $showSheet) {
MyPickerView(selection: $pickerSelection)
}
}
}
struct FrequentlyUpdatedView: View {
@Binding private var counter: Int
init(counter: Binding<Int>) {
self._counter = counter
print("\nFrequentlyUpdatedView init \(counter.wrappedValue)")
}
var body: some View {
Text("Counter: \(counter)")
}
}
struct MyPickerView: View {
@Binding private var selection: Int
init(selection: Binding<Int>) {
self._selection = selection
print("MyPickerView init")
}
var body: some View {
Picker("Snappy Picker", selection: $selection) {
ForEach(0..<100) { i in
Text("Item \(i)")
}
}
.pickerStyle(.wheel)
.labelsHidden()
}
}
Here is how the console looks like when the sheet is not open (in this case MyPickerView
located in the VStack
can be used without any issue):
FrequentlyUpdatedView init 269
MyPickerView init
FrequentlyUpdatedView init 270
MyPickerView init
Here is how the console looks like when the sheet is open (in this case MyPickerView
from the sheet cannot be properly used because picker's value resets when MyPickerView
is reinitialised:
FrequentlyUpdatedView init 368
MyPickerView init
MyPickerView init
FrequentlyUpdatedView init 369
MyPickerView init
MyPickerView init
Note: if I increase the rate of Timer
publisher to, lets say 0.01s, the MyPickerView
within the sheet becomes imposible to used while the one from ContentView
's VStack
can be used without any issue.
Any idea how to solve this?