Issue #828

From iOS 15, FocusState

Use focused(_:) for single TextField, and focused(_:equals:) for multiple TextField

struct FormView: View {

    @FocusState private var isFocused: Bool
    @State private var name = ""

    var body: some View {
        TextField("Name", text: $name)
            .focused($isFocused)
    }
}

struct FormView: View {
    enum Field: Hashable {
        case usernameField
        case passwordField
    }

    @State private var username = ""
    @State private var password = ""
    @FocusState private var focusedField: Field?

    var body: some View {
        Form {
            TextField("Username", text: $username)
                .focused($focusedField, equals: .usernameField)

            SecureField("Password", text: $password)
                .focused($focusedField, equals: .passwordField)
        }
    }
}

Wrap custom UITextField

struct FocusableTextField: UIViewRepresentable {

    final class Coordinator: NSObject, UITextFieldDelegate {
        let parent: FocusableTextField

        init(parent: FocusableTextField) {
            self.parent = parent
        }

        func textFieldDidChangeSelection(_ textField: UITextField) {
            parent.text = textField.text ?? ""
        }
    }

    @Binding var text: String
    var placeholder: String?
    @Binding var triggersFocus: Bool

    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField(frame: .zero)
        textField.delegate = context.coordinator
        textField.placeholder = placeholder
        return textField
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self)
    }

    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
        if !uiView.isFirstResponder && triggersFocus {
            uiView.becomeFirstResponder()
            triggersFocus = false
        }
    }
}

Use SwiftUI Introspect

import Introspect

TextField("Name", text: $name)
.introspectTextField { textField in
    textField.becomeFirstResponder()
}