Skip to content

Instantly share code, notes, and snippets.

@NikolajMosbaek
Created June 1, 2022 15:13
Show Gist options
  • Save NikolajMosbaek/f4f493469589dc061de1cef581e146de to your computer and use it in GitHub Desktop.
Save NikolajMosbaek/f4f493469589dc061de1cef581e146de to your computer and use it in GitHub Desktop.
With this code you can make an object Searchable and define which parameters that should be included in a search. Then you can easily call .fullyFilter(for: someString) on the object
protocol Searchable {
var keyPaths: [KeyPath<Self, String>] { get }
}
extension Searchable {
func matches(_ searchString: String) -> Bool {
for path in keyPaths {
let value = self[keyPath: path]
if value.localizedCaseInsensitiveContains(searchString) {
return true
}
}
return false
}
}
extension Sequence where Element: Searchable {
func fuzzyFilter(for searchString: String) -> [Element] {
filter { $0.matches(searchString) }
}
}
@NikolajMosbaek
Copy link
Author

@NikolajMosbaek
Copy link
Author

NikolajMosbaek commented Jun 1, 2022

Example:

struct Bus: Decodable, Identifiable, Searchable {
    enum CodingKeys: CodingKey {
        case id, name, location, destination
    }

    var id: Int
    var name: String
    var location: String
    var destination: String

    var keyPaths: [KeyPath<Bus, String>] = [\.name, \.location, \.destination]
}

struct ContentView: View {
    @State private var buses = [Bus]()
    @State private var searchText = ""

    var filteredBuses: [Bus] {
        if searchText.isEmpty {
            return buses
        } else {
            return buses.fuzzyFilter(for: searchText)
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment