SwiftUI Blog

Mastering SwiftUI: Your Guide to Building Beautiful, Intuitive Apps.

Custom Component

SwiftUI is a powerful tool, though one area ripe for improvement is the variety of components available. In this post, we’ll explore how to build a custom component: a search text field.

Adding a searchable component in SwiftUI is straightforward—you can easily add a search field to the navigation bar with just one line of code. However, the challenge arises when you want to place this component in the middle of the screen or in any position other than the navigation bar. For such custom requirements, you’ll need to build it yourself. Let me show you one possible way to achieve this.

The goal

To construct our custom search text field, we require three key components:

  1. Image: To serve as the search icon, visually indicating the purpose of the text field.
  2. TextField: This is where the user will input their search query. It’s the core component of our search functionality.
  3. Button: A clear to clear the current input in the text field.
struct CustomSearchView: View {
    @State var searchText: String = ""
    var onSubmit: (String) -> Void
    var body: some View {
        HStack {
            Image(systemName: "magnifyingglass")
            .resizable()
            .frame(width: 20, height:20)
            .foregroundStyle(Color(.systemGray))
            
            TextField("Search", text: $searchText)
            .onSubmit {
                onSubmit(searchText)
            }
            
            Button("Cancel") {
                searchText = ""

            }
        }.padding(10)
        .background(Color(.systemGray6))
        .cornerRadius(10)
    }
}

A part the graphic settings, the main parts are:

@State var searchText: String = ""
var onSubmit: (String) -> Void
  • The searchText acts as a @State variable, essential for capturing the text input from the TextField.
  • The variable var onSubmit: (String) -> Void is defined as a closure (or a callback, for those familiar with other programming languages). We utilize this closure to handle the onSubmit event of the TextField. The primary goal here is to forward the text inputted by the user to the view containing our custom search bar.

Example of Usage

struct BarSearchView: View {
    
    var body: some View {
        VStack {
            CustomSearchView(onSubmit: search)
        }.padding()
    }
    
    func searched(searched: String) {
        print(searched)
    }
}

Therefore, we define a searched function, which we pass to the CustomSearchView. This function is invoked when the user submits text via the search bar.

Enjoy creating your components.