SearchBar (iOS 15)

One of the challenges from my learning code tasked us with adding a search bar to filter topic titles for further selection. The solution provided was a hideously complicated affair using many methods/functions and leveraging UIKit into SwiftUI. It was such a nightmarish solution that I’m surprised anyone actually used it.

On searching for alternatives, it became apparent that newer versions of iOS introduced a much more simpler method of implementing a search bar.

Solution

The ‘before’:

This is typical struct displaying a list of content titles parsed from a JSON file, contained within a NavigationView, with NavigationLinks that send the user to another screen. At this point, there is no search bar functionality.

Note: all elements shown in italics are project-specific properties/methods derived from elsewhere in the project code and will be different in your project.

struct ContentView: View {
    
    @ObservedObject var model: DataUtils
    
    var body: some View {
        if model.jsonDataFile.count > 0 {
             NavigationView {
                List {
                    ForEach(model.jsonDataFile) { data in
                        NavigationLink(data.title,
                                       destination: VideoScreen(video: data))
                        
                    }
                }
                .navigationTitle(Text("All " + String(model.jsonDataFile.count) + " Videos"))
            }
        }
        else {
            ProgressView()
        }
    }
    
}

The ‘After’:

struct ContentView: View {
    
    @ObservedObject var model: DataUtils
    @State private var searchText = ""
    
    var body: some View {
        if model.jsonDataFile.count > 0 {
             NavigationView {
                List {
                    ForEach(searchResults) { data in
                        NavigationLink(data.title,
                                       destination: VideoScreen(video: data))
                        
                    }
                }
                .navigationTitle(Text("All " + String(model.jsonDataFile.count) + " Videos"))
            }
            .searchable(text: $searchText)
        }
        else {
            ProgressView()
        }
    }
    
    var searchResults: [DataModel] {
        if searchText.isEmpty {
            return model.jsonDataFile
        } else {
            return model.jsonDataFile.filter { $0.title.contains(searchText)}
        }
    }
}

The highlighted code is all that’s needed for the searchbar to display and to function.