MapKit Search
Search and filter locations on a map

Preview

Code
1import SwiftUI2import MapKit34struct MapSearchView: View {5 @State private var searchText = ""6 @State private var region = MKCoordinateRegion(7 center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194),8 span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)9 )10 @State private var searchResults: [MKMapItem] = []11 @State private var isSearching = false12 13 var body: some View {14 VStack(spacing: 0) {15 // Search Bar16 HStack {17 Image(systemName: "magnifyingglass")18 .foregroundColor(.secondary)19 20 TextField("Search locations...", text: $searchText)21 .textFieldStyle(.plain)22 .onSubmit {23 performSearch()24 }25 26 if !searchText.isEmpty {27 Button("Search") {28 performSearch()29 }30 .buttonStyle(.bordered)31 }32 }33 .padding()34 .background(Color(.systemGray6))35 .cornerRadius(10)36 .padding(.horizontal)37 .padding(.top)38 39 // Search Results40 if !searchResults.isEmpty {41 ScrollView {42 LazyVStack(spacing: 8) {43 ForEach(searchResults.indices, id: \.self) { index in44 SearchResultRow(item: searchResults[index]) {45 selectLocation(searchResults[index])46 }47 }48 }49 .padding(.horizontal)50 }51 .frame(maxHeight: 200)52 }53 54 // Map55 Map(coordinateRegion: $region, annotationItems: searchResults) { item in56 MapAnnotation(coordinate: item.placemark.coordinate) {57 VStack {58 Image(systemName: "mappin.circle.fill")59 .font(.title)60 .foregroundColor(.red)61 Text(item.name ?? "Location")62 .font(.caption)63 .padding(4)64 .background(Color.white)65 .cornerRadius(4)66 }67 }68 }69 .cornerRadius(12)70 .padding()71 }72 .overlay(73 isSearching ? 74 Color.black.opacity(0.3).overlay(75 ProgressView("Searching...")76 .padding()77 .background(Color(.systemBackground))78 .cornerRadius(8)79 ) : nil80 )81 }82 83 func performSearch() {84 guard !searchText.isEmpty else { return }85 86 isSearching = true87 88 let request = MKLocalSearch.Request()89 request.naturalLanguageQuery = searchText90 request.region = region91 92 let search = MKLocalSearch(request: request)93 search.start { response, error in94 DispatchQueue.main.async {95 isSearching = false96 if let response = response {97 searchResults = response.mapItems98 }99 }100 }101 }102 103 func selectLocation(_ item: MKMapItem) {104 region.center = item.placemark.coordinate105 region.span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)106 }107}108109struct SearchResultRow: View {110 let item: MKMapItem111 let action: () -> Void112 113 var body: some View {114 Button(action: action) {115 HStack {116 VStack(alignment: .leading, spacing: 4) {117 Text(item.name ?? "Unknown")118 .font(.headline)119 .foregroundColor(.primary)120 121 Text(item.placemark.title ?? "")122 .font(.caption)123 .foregroundColor(.secondary)124 }125 126 Spacer()127 128 Image(systemName: "chevron.right")129 .font(.caption)130 .foregroundColor(.secondary)131 }132 .padding()133 .background(Color(.systemBackground))134 .cornerRadius(8)135 .shadow(radius: 2)136 }137 .buttonStyle(.plain)138 }139}140141struct MapSearchView_Previews: PreviewProvider {142 static var previews: some View {143 MapSearchView()144 }145}