In the attached minimal reproducing app, the picker in the List works as expected while the one in the sheet resets every time the List view updates (this demo app displays a random byte value that is updated every second).
Can anyone explain why this happens and how to solve the issue, i.e. how can I have a picker in a sheet on a view without the picker getting reset when the parent view receives updates?
Somebody asked the same question here, but it is unanswered, it has different example code: https://www.hackingwithswift.com/forums/swiftui/picker-value-resets-when-in-a-sheet-but-works-fine-in-parent-view/17211
import SwiftUI
@main
struct SwiftUITestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
// MARK: - ContentView
struct ContentView: View {
@State var selectedValue: Int = 0
@State var isSheetPresented: Bool = false
@State var randomByte: UInt8 = 0
var body: some View {
List {
Text("Frequently updated random byte: \(randomByte)")
Text("Note how the picker works as expected here:")
MyPicker()
Text("But not within a sheet:")
Button("Select a value inside a sheet") {
isSheetPresented = true
}
}
.sheet(
isPresented: $isSheetPresented,
onDismiss: {
isSheetPresented = false
},
content: {
List {
VStack(alignment: .leading, spacing: 16) {
Text("Select a value close to the bottom of the drop down menu.")
Text("Then open the drop down menu again.")
Text("Note that the drop down menu scrolls each time `randomByte` changes.")
}
MyPicker()
}
}
)
.task {
while true {
try! await Task.sleep(nanoseconds: 1_000_000_000)
randomByte = UInt8.random(in: .min ... .max)
}
}
}
}
// MARK: MyPicker
struct MyPicker: View {
@State var selectedValue: Int = 0
var body: some View {
Picker("Value", selection: $selectedValue) {
ForEach(0..<100, id: \.self) { value in
Text("\(value)").tag(value)
}
}
.onChange(of: selectedValue) { _ in
print("•••• selectedValue", selectedValue)
}
}
}
// MARK: Preview
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
You aren't using the selectedValue variable in ContentView. So nobody knows how the selectedValue variable in MyPicker is supposed to affect ContentView. If the selectedValue variable in MyPicker is supposed to affect ContentView, then make it Binding.
Isn't that unrelated to the issue I described? (The selectedValue doesn't need to affect ContentView in order to demonstrate the issue.) Here is the issue again: While the sheet is open, and I try to scroll through the picke's items, it is impossible to reach to the bottom, because it will scroll back to the top once every second, each time the
randomByte
is updated. Why is this, and how can I make the picker in the sheet not reset/scroll back to the top every timerandomByte
is updated?