TextField Recommendations / Autocomplete – SwiftUI macOS and iOS

Another weekend, another set of improvements for MarsManaged. This time, I focused on adding an autocompletion feature for Tags.

Let me provide some context first… In MarsManaged, cards may be linked to one or multiple tags. In the below example, the “Welcome to MarsManaged!” card is linked to the tag “Samples” (yellow arrow). 

Screen Shot 2022 03 20 at 8 18 10 PM

To link one card to more tags, a user can start directly typing on the “+Tag” TextField. Once the user presses enter, the system will either link it to the right tag or —if it does not exist— create a new one and link it. 

To streamline the process, I wanted recommendations to start appearing once the user started typing.

– The bad news is that there’s no built-in SwiftUI methods for it.

– The good news is that by leveraging .onChange and .popover you can get the same functionality:

AutompleteExample

Here’s the section of the code that generates it:

@State private var popupTagsPresented = false

 

TextField(“PlaceholderText”, text: $variableLinkedTo)

.onChange(of: variableLinkedTo, perform: { newTag in

    //Do something with new tag to know when you want to show or not the popup, here assuming always

    popupTagsPresented = true

})

.popover(isPresented: $popupTagsPresented, arrowEdge: .top) {

    let filteredMatches = [“some stuff”, “somethingElse”]//Array of items to show (likely you’d grab it from Core Data / some model function)

    VStack(alignment: .leading, spacing: 4){

        ForEach(filteredMatches) { suggestion in

            Button{

                //When user clicks on the suggestion, replace text with suggestion and process it

                variableLinkedTo = suggestion.name

                processText()

            }label: {

                Label(suggestion.name ?? “”, systemImage: “someIcon”)

            }

            .buttonStyle(.borderless)

        }

    }.padding(10)

}

The above code uses .onChange to detect when the user starts typing in the TextField and flips the popupTagsPresented to true, which in turn shows the popover. 

The popover then displays the array of suggestions, each of them being its own Button. When a suggestion button is clicked, the TextField text is replaced by the selected suggestion and a function processText() is called. For my use case that function will link the tag to the card and then reset the TextField to nil so it’s ready to take new user input. 

Screen Shot 2022 03 20 at 8 35 44 PM

Happy Coding! Thoughts, suggestions? Reach me @MarcMasVi

 

Marc