title: UITextField in SwiftUI resulting to "Modifying state during view update, this will cause undefined behavior."
body: <p>I am trying to create a system in SwiftUI that will give me control over which textfield is first responder so I can easily create a responder chain.</p>
  <p>I created a <code>UIViewRepresentable</code> that gets an environment value of a <code>Binding</code> with boolean type and I am changing the state according to these functions <code>textFieldDidBeginEditing</code> and <code>textFieldDidEndEditing</code>.</p>
  <pre><code>struct TextField: UIViewRepresentable {
   
      @Binding var text: String
      @Environment(\.isSecureField) var isSecureField: Bool
      @Environment(\.isFirstResponder) var isFirstResponder: Binding&lt;Bool&gt;?
      @Environment(\.placeholder) var placeholder: String?
      @Environment(\.keyboardType) var keyboardType: UIKeyboardType
      @Environment(\.returnKeyType) var returnKeyType: UIReturnKeyType
      @Environment(\.textContentType) var contentType: UITextContentType?
      @Environment(\.autoCapitalization) var  autoCapitalization: Bool
      @Environment(\.autoCorrection) var  autoCorrection: Bool
      @Environment(\.font) var font: Font?
      
      let onCommit: (() -&gt; Bool)?
      
      init(
          text: Binding&lt;String&gt;,
          onCommit:(() -&gt; Bool)? = nil) {
  
          self._text = text
          self.onCommit = onCommit
      
      }
      
      func makeUIView(context: Context) -&gt; UITextField {
          let textField = UITextField()
          textField.delegate = context.coordinator
          syncValues(context: context, textField: textField)
          return textField
      }
  
      func updateUIView(_ uiView: UITextField, context: Context) {
          syncValues(context: context, textField: uiView)
   
          if let isFirstReposnderValue = isFirstResponder?.wrappedValue {
              switch isFirstReposnderValue {
              case true:
                  uiView.becomeFirstResponder()
              case false:
                  uiView.resignFirstResponder()
              }
          }
      }
      
      private func syncValues(context: Context, textField: UITextField) {
          textField.text = text
          textField.isSecureTextEntry = isSecureField
          textField.textContentType = contentType
          textField.keyboardType = keyboardType
          textField.placeholder = placeholder
          textField.font = UIFont.preferredFont(from: font)
          textField.autocapitalizationType = autoCapitalization ? .sentences : .none
          textField.returnKeyType = returnKeyType
          textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
          textField.autocorrectionType = autoCorrection ? .yes : .no
      }
      
      func makeCoordinator() -&gt; Coordinator {
          return Coordinator( parent: self  )
      }
      
      class Coordinator: NSObject, UITextFieldDelegate {
          
          private let parent: TextField
          
          init(parent: TextField) {
              self.parent = parent
          }
          
          func textFieldShouldReturn(_ textField: UITextField) -&gt; Bool {
              return parent.onCommit?() ?? true
          }
          
          func textFieldDidChangeSelection(_ textField: UITextField) {
              parent.$text.wrappedValue = textField.text ?? &quot;&quot;
          }
  
          func textFieldDidBeginEditing(_ textField: UITextField) {
              parent.isFirstResponder?.wrappedValue =  true
  
          }
  
          func textFieldDidEndEditing(_ textField: UITextField) {
              parent.isFirstResponder?.wrappedValue =  false
          }
  
      }
  }
  </code></pre>
  <p>Also I create a new constructor for Binding with boolean type so I can use a Hashable (like an enum) so I can have more than two states and no true or false.</p>
  <pre><code>extension Binding where Value == Bool {
      
      init&lt;V: Hashable&gt;(tag: V, selection: Binding&lt;V?&gt;) {
          self.init { () -&gt; Value in
              selection.wrappedValue == tag
          } set: { (newValue) in
              selection.wrappedValue = newValue ?  tag : nil
          }
      }
  }
  </code></pre>
  <p>This is an example on how I am using it:</p>
  <pre><code>class TestLoginViewModel:ObservableObject {
      
      @Published var email: String = &quot;&quot;
      @Published var password: String = &quot;&quot;
  }
  
  struct TestLoginView: View {
      
      enum Field {
          case email
          case password
      }
      
      @StateObject private var viewModel: TestLoginViewModel
      @State private var activeField: Field?
      
      init(viewModel: TestLoginViewModel = .init()) {
          self._viewModel = StateObject(wrappedValue: viewModel)
      }
    
      
      var body: some View {
          VStack(spacing: 8) {
              
              TextField(text: $viewModel.email, onCommit: { () -&gt; Bool in
                  activeField = .password
                  return true
              })
              .placeholder(L10n.email)
              .isFirstReponder(.init(tag: .email, selection: $activeField))
              .returnKeyType(.next)
              .keyboard(.emailAddress)
              
              TextField(text: $viewModel.password, onCommit: { () -&gt; Bool in
                  activeField = nil
                  return true
              })
              .placeholder(L10n.password)
              .isSecureField(true)
              .isFirstReponder(.init(tag: .password, selection: $activeField))
              .returnKeyType(.send)
              .keyboard(.emailAddress)
          }
      }
  }
  </code></pre>
  <p>But I am getting:</p>
  <blockquote>
  <p>Modifying state during view update, this will cause undefined behavior.</p>
  </blockquote>
  <p><a href="https://i.stack.imgur.com/os0Eo.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/os0Eo.png" alt="enter image description here" /></a></p>