SwiftUI - Mutable @FocusState for child view?
Asked Answered
H

2

28

I have a parent view with a @FocusState variable that I want to pass into a child view that contains a TextField. I want to be able to change the FocusState from within the child view, but I get the errors Cannot assign to property: 'self' is immutable and Cannot assign value of type 'Bool' to type 'FocusState<Bool>.Binding'.

Parent view:

struct ParentView: View {
    @State private var text: String
    @FocusState private var isEditing: Bool
    
    var body: some View {
        ChildView($text, $isEditing)
    }
}

struct ChildView: View {
    @Binding var text: String
    var isEditing: FocusState<Bool>.Binding
    
    init(_ text: Binding<String>, _ isEditing: FocusState<Bool>.Binding) {
        self._text = text
        self.isEditing = isEditing
    }
    
    var body: some View {
        TextField("Username", text: $text)
            .focused(isEditing)
        
        Button("Click me!") {
            isEditing = false  // Error here
        }
    }
}
Huddle answered 23/10, 2021 at 4:35 Comment(0)
I
20

Just assign via binding to wrapped value, like

Button("Click me!") {
    isEditing.wrappedValue = false  // << here !!
}
Incommunicable answered 23/10, 2021 at 4:42 Comment(2)
Works! Is there any way I can have isEditing only appear for that particular TextField? When I have multiple ChildViews and tap one it triggers it on every item, not just the one in focus.Huddle
Disregard my last comment, I was able to achieve this with the equals: focused parameterHuddle
P
1

You can use FocusState.Binding in order to pass your focus state to your child view.

The code snippet below shows how to implement it:

struct ParentView: View {
    @State private var text = ""
    @FocusState private var isEditing: Bool

    var body: some View {
        ChildView(text: $text, isEditing: $isEditing)
            .onChange(of: isEditing) { oldValue, newValue in
                print(newValue) // Track the changes of focus state
            }
    }
}

struct ChildView: View {
    @Binding var text: String
    @FocusState.Binding var isEditing: Bool

    var body: some View {
        TextField("Username", text: $text)
            .focused($isEditing)

        Button("Click me!") {
            isEditing = false
        }
    }
}
Placid answered 1/6 at 16:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.