title: In SwiftUI, how do I know when a Picker selection was changed? Why doesn't didSet work?
body: <p>I have a <code>Picker</code> in a SwiftUI <code>Form</code>, and I'm trying to process the value whenever the picker changes. I expected to be able to do this with <code>didSet</code> on a variable that represents the currently selected value.</p>
  
  <pre><code>import SwiftUI
  
  struct ContentView: View {
  
      enum TransmissionType: Int {
          case automatic
          case manual
      }
  
      @State private var selectedTransmissionType: Int = TransmissionType.automatic.rawValue {
          didSet {
              print("selection changed to \(selectedTransmissionType)")
          }
      }
  
      private let transmissionTypes: [String] = ["Automatic", "Manual"]
  
      var body: some View {
          NavigationView {
              Form {
                  Section {
                      Picker(selection: $selectedTransmissionType,
                             label: Text("Transmission Type")) {
                          ForEach(0 ..&lt; transmissionTypes.count) {
                              Text(self.transmissionTypes[$0])
                          }
                      }
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>The <code>Picker</code> UI works (mostly) as expected: I can see the default value is selected, tap into the picker, it opens a new view, I can select the other value, and then it goes back to the main form and shows me the new value is selected. However, <code>didSet</code> is never called.</p>
  
  <p>I saw <a href="https://stackoverflow.com/questions/58676483/is-there-a-way-to-call-a-function-when-a-swiftui-picker-selection-changes">this question</a>, but it seems odd to me to add more to my <code>View</code> code instead of just processing the new value when the variable changes, if that is even possible. Is it better to use <code>onReceive</code> even though it results in a more complicated view? My main question is: <strong>What's wrong with my code to prevent <code>didSet</code> from being called?</strong></p>
  
  <p>I used <a href="https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-a-picker-and-read-values-from-it" rel="noreferrer">this example</a> to get to this point.</p>
  
  <p>Beyond my regular question, I have a few others about this example:</p>
  
  <p><strong>A)</strong> It seems weird how I have an <code>enum</code> and also an <code>Array</code> to represent the same two values. Can someone also suggest a better way to structure it to avoid this redundancy? I considered a <code>TransmissionType</code> object, but that seemed like overkill compared to an <code>enum</code>... maybe it's not?</p>
  
  <p><strong>B)</strong> When tapping into the picker, the screen with the picker options slides over, and then the two options jump up a bit. This feels jarring and jumpy and a bad user experience. Am I doing something wrong here that's causing the bad UX? Or is it probably a SwiftUI bug? I'm getting this error every time I change the picker:</p>
  
  <p><code>[TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window.</code></p>