Commit 118673de authored by Ariba Siddiqui's avatar Ariba Siddiqui
Browse files

Merge branch 'main' into 'main'

Search Function: added comments

See merge request !1
parents 59db5e27 2a54c0a2
......@@ -11,6 +11,7 @@ import MapKit
class LocationService: NSObject, ObservableObject {
// Differnt search states
enum LocationStatus: Equatable {
case idle
case noResults
......@@ -19,6 +20,9 @@ class LocationService: NSObject, ObservableObject {
case result
}
// queryFragment used in view gets updated every time the user types something
// default status is idle
// searchResults contains all the results from the queries
@Published var queryFragment: String = ""
@Published private(set) var status: LocationStatus = .idle
@Published private(set) var searchResults: [MKLocalSearchCompletion] = []
......@@ -26,15 +30,21 @@ class LocationService: NSObject, ObservableObject {
private var queryCancellable: AnyCancellable?
private let searchCompleter: MKLocalSearchCompleter!
// initiate the search completer, set the delegate on self
init(searchCompleter: MKLocalSearchCompleter = MKLocalSearchCompleter()) {
self.searchCompleter = searchCompleter
super.init()
self.searchCompleter.delegate = self
// receive a stream from the queryFragment in the view
// debounce (wait) for 250miliseconds before pushing the event further
// sink returns the updated string after waiting the specified amount of time
queryCancellable = $queryFragment
.receive(on: DispatchQueue.main)
.debounce(for: .milliseconds(250), scheduler: RunLoop.main, options: nil)
.sink(receiveValue: { fragment in
// if fragment isn't empty then set the queryFrament to the current updated string
self.status = .isSearching
if !fragment.isEmpty {
self.searchCompleter.queryFragment = fragment
......@@ -46,8 +56,12 @@ class LocationService: NSObject, ObservableObject {
}
}
// every time the queryFragment gets updated these functions get called
extension LocationService: MKLocalSearchCompleterDelegate {
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
// query the current input, filter out the results that have subtitles
// results with no subtitles are usually countries and cities
// remove filter if you want to get points of interest as well
self.searchResults = completer.results.filter({ $0.subtitle == "" })
self.status = completer.results.isEmpty ? .noResults : .result
}
......
......@@ -23,6 +23,10 @@ struct ContentView: View {
Section(header: Text("Search")) {
ZStack(alignment: .trailing) {
TextField("Search", text: $locationService.queryFragment)
// while user is typing input it sends the current query to the location service
// which in turns sets its status to searching; when searching status is set on
// searching then a clock symbol will be shown beside the search box
if locationService.status == .isSearching {
Image(systemName: "clock")
.foregroundColor(Color.gray)
......@@ -39,7 +43,8 @@ struct ContentView: View {
default: return AnyView(EmptyView())
}
}.foregroundColor(Color.gray)
// display the results as a list
ForEach(locationService.searchResults, id: \.self) {
completionResult in Text(completionResult.title)
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment