Search code examples
swiftswiftuiuikituitextfielduiviewrepresentable

Update inputAccessoryView in SwiftUI (UIViewRepresentable)


I want to display search results above the keyboard with SwiftUI. For this, I made a UIViewRepresentable for UITextField and set the inputAccessoryView accordingly.

Everything is displayed correctly, but the inputAccessoryView is not updating.

 struct V_ToolbarTextField<Content: View>: UIViewRepresentable {
    
    var title: String
    @Binding var text: String
    var keyType: UIKeyboardType
    
    var toolbarContent: Content
        
    init(_ title: String,
         text: Binding<String>,
         keyType: UIKeyboardType = .alphabet,
         toolbarContent: Content) {
        self.title = title
        self._text = text
        self.keyType = keyType
        self.toolbarContent = toolbarContent
    }
    
    
    func makeUIView(context: Context) -> UITextField {
        let textfield = UITextField()
        textfield.keyboardType = keyType
        textfield.placeholder = title

        let textUIKit = UIHostingController(rootView: toolbarContent)
        textUIKit.view.frame = CGRect(x: 0, y: 0, width: 800, height: 60)

        textfield.inputAccessoryView = textUIKit.view
        return textfield
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
    }
}

This is how I am passing the inputAccessoryView's content:

 V_ToolbarTextField("Title",
                    text: $gameNameFilter, 
                    toolbarContent: 
                     viewContainingSearchResults())

I've tried binding toolbarContent and setting the inputAccessoryView in updateUIView(). I've also tried creating a Coordinator class and setting the UITextField's delegate to it, hoping to use a UITextFieldDelegate function to update it, but I don't know which one and I wasn't able to set the delegate correctly.


Solution

  • I couldn't get it to work and ditched the inputAccessoryView for a VStack with the ToolBar at the bottom. I hide it when the keyboard is shown.

    @State var keyboardOpen = false
    
    VStack {
        
        // everything else...
        
        if (keyboardOpen) {
            V_FilteredGameList(filter: vm.gameName, action: { game in
                vm.setExistingGame(game: game)
                hideKeyboard()
            })
        }
    }
    .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { _ in
            keyboardOpen = true
    }
    .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
            keyboardOpen = false
    }