I have a search bar in SwiftUi and it doesn't react the way I am wanting it to. I have gone through a few attempts at using .overlay and .zIndex but that did not work as intended. It added the SearchView, but it still displayed the other text. Here's the code I have currently. What I'm intending to do is search for a location using MapKit, which I have working. I included the code for that file in case it's needed. I just cannot get the search bar to react the way I want.
This is my WelcomeView.Swift code:
import SwiftUI
struct WelcomeView: View {
@EnvironmentObject var locationManager: LocationManager
@ObservedObject var locationSearch: LocationSearch
@State private var isSearching = false
var body: some View {
VStack {
if isSearching {
LocationSearchView(locationSearch: locationSearch)
.zIndex(1)
// .background(Color.blue)
} else {
VStack(spacing: 10) {
Text("Welcome to App!")
.bold().font(.largeTitle)
Text("Blah Blah Blah Blah Blah Blah")
.font(.title)
}
.multilineTextAlignment(.center)
.padding()
VStack() {
Text("Blah Blah Blah Blah Blah")
Text("Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah")
}
.padding()
.font(.headline)
ZStack {
VStack {
TextField("Search", text: $locationSearch.queryFragment, onEditingChanged: { isEditing in isSearching = isEditing
})
.padding(.horizontal)
.padding(.vertical, 8)
.frame(width: 535, height: 70)
.background(.thinMaterial)
.cornerRadius(10)
Button(action: {
locationManager.requestLocation()
}, label: {
HStack {
Image(systemName: "location.fill")
Text("Allow Location Services")
.font(.title)
}
.frame(width: 500, height: 70)
})
}
.zIndex(0)
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
This is the LocationSearch.swift code:
import Foundation
import Combine
import MapKit
class LocationSearch: NSObject, ObservableObject {
enum LocationStatus: Equatable {
case idle
case noResults
case isSearching
case error(String)
case result
}
@Published var queryFragment: String = ""
@Published private(set) var status: LocationStatus = .idle
@Published private(set) var searchResults: [MKLocalSearchCompletion] = []
private var queryCancellable: AnyCancellable?
private let searchCompleter: MKLocalSearchCompleter!
init(searchCompleter: MKLocalSearchCompleter = MKLocalSearchCompleter()) {
self.searchCompleter = searchCompleter
super.init()
self.searchCompleter.delegate = self
queryCancellable = $queryFragment
.receive(on: DispatchQueue.main)
.debounce(for: .milliseconds(250), scheduler: RunLoop.main, options: nil)
.sink(receiveValue: { fragment in
self.status = .isSearching
if !fragment.isEmpty {
self.searchCompleter.queryFragment = fragment
} else {
self.status = .idle
self.searchResults = []
}
})
}
}
extension LocationSearch: MKLocalSearchCompleterDelegate {
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
self.searchResults = completer.results.filter({ $0.subtitle == "" })
self.status = completer.results.isEmpty ? .noResults : .result
}
func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
self.status = .error(error.localizedDescription)
}
}
This is a gif of how I am wanting it to function
In this GIF, upon tapping the search bar, the search bar moves smoothly to the top of the screen, fades everything else out, and brings up the keyboard. Then the user can start typing and results will display.
I have all of the search logic working but I can't get the UI to react in the way I am envisioning when tapping the search bar.