skip to Main Content

I have a SwiftUI app that is targeting iOS 14 as well.
I want to use the focus state only for the iOS 15 version. I don’t mind much about the iOS 14 version. As focusState is only available for iOS 15.

@FocusState private var isUsernameFocused: Bool = false

I tried to define with #available but it is not working.
Again, I just want to use it with iOS 15 machines, but I need a way to declare it.

I want to use it on a press of a button.
Whenever I press the button, I want to active the keyboard for the text field.
How can I do this on SwiftUI?

2

Answers


  1. You didn’t say how you want to use it, but generally the approach can be like this:

    1. Create a View, which will be compatible with iOS 15 only and will contain @FocusState, as well as encapsulate any behaviors specific to the focus (they can be predefined or passed in on init):
    struct FocusableUsername: View {
        @FocusState private var isUsernameFocused: Bool
        @State private var username = "Anonymous"
    
        var body: some View {
            VStack {
                TextField("Enter your username", text: $username)
                    .focused($isUsernameFocused)
    
                Button("Toggle Focus") {
                    isUsernameFocused.toggle()
                }
            }
        }
    }
    
    1. Now in your main view, use if #available(iOS 15, * to show this FocusableUsername, or just a regular `TextField (or whatever the component you are using):
    struct MainView: View {
        var body: some View {
            if #available(iOS 15, *) {
                FocusableUsername()
            } else {
                TextField(...)
            }
        }
    }
    

    Of course you may need to control the behavior of this field from outside, so you can pass a main view as a delegate to it for example, or pass some closures to run – many options there.

    Login or Signup to reply.
  2. This is what I came up with:

    public func autoFocusTextField(
        title: String,
        text: Binding<String>,
        lineLimit: Int,
        multilineTextAlignment: TextAlignment
    ) -> some View {
        if #available(iOS 15, *) {
            return AutoFocusTextField(
                title: title,
                isFocused: FocusState(),
                text: text,
                lineLimit: lineLimit,
                multilineTextAlignment: multilineTextAlignment
            )
        } else {
            return TextField(title, text: text)
                .lineLimit(lineLimit)
                .multilineTextAlignment(multilineTextAlignment)
        }
    }
    
    @available(iOS 15.0, *)
    struct AutoFocusTextField: View {
        let title: String
        @FocusState var isFocused: Bool
        @Binding var text: String
        let lineLimit: Int
        let multilineTextAlignment: TextAlignment
    
        var body: some View {
            TextField(title, text: $text)
                .focused($isFocused)
                .lineLimit(lineLimit)
                .multilineTextAlignment(multilineTextAlignment)
                .onAppear {
                    isFocused = true
                }
        }
    }
    

    From your main view you’d call autoFocusTextField with the required arguments (obviously, you can tweak them).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search