UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Picker value resets when in a sheet, but works fine in parent View

Forums > SwiftUI

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?

1      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.