Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI @FocusState - how to give it initial value

Tags:

ios

swift

swiftui

I am excited to see the TextField enhancement: focused(...): https://developer.apple.com/documentation/swiftui/view/focused(_:)

I want to use it to show a very simple SwitfUI view that contains only one TextField that has the focus with keyboard open immediately. Not able to get it work:

    struct EditTextView: View {
        @FocusState private var isFocused: Bool
        @State private var name = "test"
// ...
        var body: some View {
            NavigationView {
                VStack {
                    HStack {
                        TextField("Enter your name", text: $name).focused($isFocused)
                            .onAppear {
                                isFocused = true
                            }
// ...

Anything wrong? I have trouble to give it default value.

like image 904
Sean Avatar asked Jun 21 '21 19:06

Sean


2 Answers

I was also not able to get this work on Xcode 13, beta 5. To fix, I delayed the call to isFocused = true. That worked!

The theory I have behind the bug is that at the time of onAppear the TextField is not ready to become first responder, so isFocused = true and iOS calls becomeFirstResponder behind the scenes, but it fails (ex. the view hierarchy is not yet done setting up).

struct MyView: View {

  @State var text: String
  @FocusState private var isFocused: Bool

  var body: some View {
    Form {
      TextEditor(text: $text)
        .focused($isFocused)
        .onChange(of: isFocused) { isFocused in
          // this will get called after the delay
        }
        .onAppear {
          // key part: delay setting isFocused until after some-internal-iOS setup
          DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
            isFocused = true
          }
        }
    }
  }
}
like image 162
kgaidis Avatar answered Sep 28 '22 07:09

kgaidis


I was also not able to get this work on Xcode 13, beta 5. To fix, I delayed the call to isFocused = true. That worked!

It also works without delay.

DispatchQueue.main.async {
    isFocused = true
}
like image 29
schornon Avatar answered Sep 28 '22 08:09

schornon