From ffaa2bd319701f1980e9e51233bed246c4a88bfd Mon Sep 17 00:00:00 2001 From: Lucas Jorge Hubert Date: Wed, 17 May 2023 17:19:06 -0300 Subject: [PATCH 1/2] refactor and get selected Location information --- MarvelUI/App/MarvelUIApp.swift | 3 ++- MarvelUI/Core/Home/View/HomeView.swift | 3 ++- MarvelUI/Core/Home/View/UberMapViewRepresentable.swift | 5 ++++- .../Core/LocationSearch/View/LocationSeachView.swift | 10 +++++++--- .../ViewModel/LocationSearchViewModel.swift | 9 +++++++-- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/MarvelUI/App/MarvelUIApp.swift b/MarvelUI/App/MarvelUIApp.swift index f7c2e76..47b5b3c 100644 --- a/MarvelUI/App/MarvelUIApp.swift +++ b/MarvelUI/App/MarvelUIApp.swift @@ -9,11 +9,12 @@ import SwiftUI @main struct MarvelUIApp: App { - let persistenceController = PersistenceController.shared + @StateObject var locationViewModel = LocationSearchViewModel() var body: some Scene { WindowGroup { HomeView() + .environmentObject(locationViewModel) } } } diff --git a/MarvelUI/Core/Home/View/HomeView.swift b/MarvelUI/Core/Home/View/HomeView.swift index 447fd01..e32feb1 100644 --- a/MarvelUI/Core/Home/View/HomeView.swift +++ b/MarvelUI/Core/Home/View/HomeView.swift @@ -9,13 +9,14 @@ import SwiftUI struct HomeView: View { @State private var showLocationSearchView = false + var body: some View { ZStack(alignment: .top) { UberMapViewRepresentable() .ignoresSafeArea() if showLocationSearchView { - LocationSeachView() + LocationSeachView(showLocationSearchView: $showLocationSearchView) } else { LocationSearchActivationView() .padding(.vertical, 72) diff --git a/MarvelUI/Core/Home/View/UberMapViewRepresentable.swift b/MarvelUI/Core/Home/View/UberMapViewRepresentable.swift index 5fa2110..df6425e 100644 --- a/MarvelUI/Core/Home/View/UberMapViewRepresentable.swift +++ b/MarvelUI/Core/Home/View/UberMapViewRepresentable.swift @@ -11,6 +11,7 @@ import MapKit struct UberMapViewRepresentable: UIViewRepresentable { let mapView = MKMapView() let locationManager = LocationManager() + @EnvironmentObject var locationViewModel: LocationSearchViewModel func makeUIView(context: Context) -> some UIView { mapView.delegate = context.coordinator @@ -22,7 +23,9 @@ struct UberMapViewRepresentable: UIViewRepresentable { } func updateUIView(_ uiView: UIViewType, context: Context) { - + if let selectedLocation = locationViewModel.selectedLocation { + print("DEBUG: Selected location in map view \(selectedLocation)") + } } func makeCoordinator() -> MapCoordinator { diff --git a/MarvelUI/Core/LocationSearch/View/LocationSeachView.swift b/MarvelUI/Core/LocationSearch/View/LocationSeachView.swift index 433ee28..6152674 100644 --- a/MarvelUI/Core/LocationSearch/View/LocationSeachView.swift +++ b/MarvelUI/Core/LocationSearch/View/LocationSeachView.swift @@ -9,8 +9,8 @@ import SwiftUI struct LocationSeachView: View { @State private var startLocationText = "" - @State private var destinationLocationText = "" - @StateObject var viewModel = LocationServiceViewModel() + @Binding var showLocationSearchView: Bool + @EnvironmentObject var viewModel: LocationSearchViewModel var body: some View { VStack { @@ -55,6 +55,10 @@ struct LocationSeachView: View { VStack(alignment: .leading) { ForEach(viewModel.resuls, id: \.self) { result in LocationSearchResultCell(title: result.title, subtitle: result.subtitle) + .onTapGesture { + showLocationSearchView.toggle() + viewModel.selectLocation(result.title) + } } } } @@ -66,6 +70,6 @@ struct LocationSeachView: View { struct LocationSeachView_Previews: PreviewProvider { static var previews: some View { - LocationSeachView() + LocationSeachView(showLocationSearchView: .constant(true)) } } diff --git a/MarvelUI/Core/LocationSearch/ViewModel/LocationSearchViewModel.swift b/MarvelUI/Core/LocationSearch/ViewModel/LocationSearchViewModel.swift index c084b4c..5753ae0 100644 --- a/MarvelUI/Core/LocationSearch/ViewModel/LocationSearchViewModel.swift +++ b/MarvelUI/Core/LocationSearch/ViewModel/LocationSearchViewModel.swift @@ -8,9 +8,10 @@ import Foundation import MapKit -class LocationServiceViewModel: NSObject, ObservableObject { +class LocationSearchViewModel: NSObject, ObservableObject { @Published var resuls = [MKLocalSearchCompletion]() + @Published var selectedLocation: String? private let searchCompleter = MKLocalSearchCompleter() var queryFragment: String = "" { didSet { @@ -23,11 +24,15 @@ class LocationServiceViewModel: NSObject, ObservableObject { searchCompleter.delegate = self searchCompleter.queryFragment = queryFragment } + + func selectLocation(_ location: String) { + self.selectedLocation = location + } } // MARK: - MKLocalSearchCompleterDelegate -extension LocationServiceViewModel: MKLocalSearchCompleterDelegate { +extension LocationSearchViewModel: MKLocalSearchCompleterDelegate { func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) { self.resuls = completer.results } From ebb3a19b7b9ce8cbac529c40ed137a4b67889c1e Mon Sep 17 00:00:00 2001 From: Lucas Jorge Hubert Date: Wed, 17 May 2023 17:40:08 -0300 Subject: [PATCH 2/2] getting coordinates --- MarvelUI.xcodeproj/project.pbxproj | 8 ++--- MarvelUI/Core/Home/View/HomeView.swift | 2 +- .../Home/View/UberMapViewRepresentable.swift | 4 +-- ...achView.swift => LocationSearchView.swift} | 6 ++-- .../ViewModel/LocationSearchViewModel.swift | 29 +++++++++++++++++-- 5 files changed, 36 insertions(+), 13 deletions(-) rename MarvelUI/Core/LocationSearch/View/{LocationSeachView.swift => LocationSearchView.swift} (92%) diff --git a/MarvelUI.xcodeproj/project.pbxproj b/MarvelUI.xcodeproj/project.pbxproj index f44a1dc..91acc85 100644 --- a/MarvelUI.xcodeproj/project.pbxproj +++ b/MarvelUI.xcodeproj/project.pbxproj @@ -20,7 +20,7 @@ C9CFFE812A151F7400708A15 /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CFFE802A151F7400708A15 /* LocationManager.swift */; }; C9CFFE872A153D7500708A15 /* LocationSearchActivationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CFFE862A153D7500708A15 /* LocationSearchActivationView.swift */; }; C9CFFE892A153FA800708A15 /* MapViewActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CFFE882A153FA800708A15 /* MapViewActionButton.swift */; }; - C9CFFE8B2A15410900708A15 /* LocationSeachView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CFFE8A2A15410900708A15 /* LocationSeachView.swift */; }; + C9CFFE8B2A15410900708A15 /* LocationSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CFFE8A2A15410900708A15 /* LocationSearchView.swift */; }; C9CFFE8D2A15447800708A15 /* LocationSearchResultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CFFE8C2A15447800708A15 /* LocationSearchResultCell.swift */; }; C9CFFE8F2A154F1900708A15 /* LocationSearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CFFE8E2A154F1900708A15 /* LocationSearchViewModel.swift */; }; /* End PBXBuildFile section */ @@ -60,7 +60,7 @@ C9CFFE802A151F7400708A15 /* LocationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = ""; }; C9CFFE862A153D7500708A15 /* LocationSearchActivationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSearchActivationView.swift; sourceTree = ""; }; C9CFFE882A153FA800708A15 /* MapViewActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewActionButton.swift; sourceTree = ""; }; - C9CFFE8A2A15410900708A15 /* LocationSeachView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSeachView.swift; sourceTree = ""; }; + C9CFFE8A2A15410900708A15 /* LocationSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSearchView.swift; sourceTree = ""; }; C9CFFE8C2A15447800708A15 /* LocationSearchResultCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSearchResultCell.swift; sourceTree = ""; }; C9CFFE8E2A154F1900708A15 /* LocationSearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSearchViewModel.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -230,7 +230,7 @@ isa = PBXGroup; children = ( C9CFFE862A153D7500708A15 /* LocationSearchActivationView.swift */, - C9CFFE8A2A15410900708A15 /* LocationSeachView.swift */, + C9CFFE8A2A15410900708A15 /* LocationSearchView.swift */, C9CFFE8C2A15447800708A15 /* LocationSearchResultCell.swift */, ); path = View; @@ -374,7 +374,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C9CFFE8B2A15410900708A15 /* LocationSeachView.swift in Sources */, + C9CFFE8B2A15410900708A15 /* LocationSearchView.swift in Sources */, C9CFFE4D2A1517A200708A15 /* Persistence.swift in Sources */, C9CFFE7D2A151D2400708A15 /* HomeView.swift in Sources */, C9CFFE812A151F7400708A15 /* LocationManager.swift in Sources */, diff --git a/MarvelUI/Core/Home/View/HomeView.swift b/MarvelUI/Core/Home/View/HomeView.swift index e32feb1..93b798a 100644 --- a/MarvelUI/Core/Home/View/HomeView.swift +++ b/MarvelUI/Core/Home/View/HomeView.swift @@ -16,7 +16,7 @@ struct HomeView: View { .ignoresSafeArea() if showLocationSearchView { - LocationSeachView(showLocationSearchView: $showLocationSearchView) + LocationSearchView(showLocationSearchView: $showLocationSearchView) } else { LocationSearchActivationView() .padding(.vertical, 72) diff --git a/MarvelUI/Core/Home/View/UberMapViewRepresentable.swift b/MarvelUI/Core/Home/View/UberMapViewRepresentable.swift index df6425e..0d13b2e 100644 --- a/MarvelUI/Core/Home/View/UberMapViewRepresentable.swift +++ b/MarvelUI/Core/Home/View/UberMapViewRepresentable.swift @@ -23,8 +23,8 @@ struct UberMapViewRepresentable: UIViewRepresentable { } func updateUIView(_ uiView: UIViewType, context: Context) { - if let selectedLocation = locationViewModel.selectedLocation { - print("DEBUG: Selected location in map view \(selectedLocation)") + if let coordinate = locationViewModel.selectedLocationCoordinate { + print("DEBUG: Selected coordinate in map view \(coordinate)") } } diff --git a/MarvelUI/Core/LocationSearch/View/LocationSeachView.swift b/MarvelUI/Core/LocationSearch/View/LocationSearchView.swift similarity index 92% rename from MarvelUI/Core/LocationSearch/View/LocationSeachView.swift rename to MarvelUI/Core/LocationSearch/View/LocationSearchView.swift index 6152674..a75d290 100644 --- a/MarvelUI/Core/LocationSearch/View/LocationSeachView.swift +++ b/MarvelUI/Core/LocationSearch/View/LocationSearchView.swift @@ -7,7 +7,7 @@ import SwiftUI -struct LocationSeachView: View { +struct LocationSearchView: View { @State private var startLocationText = "" @Binding var showLocationSearchView: Bool @EnvironmentObject var viewModel: LocationSearchViewModel @@ -57,7 +57,7 @@ struct LocationSeachView: View { LocationSearchResultCell(title: result.title, subtitle: result.subtitle) .onTapGesture { showLocationSearchView.toggle() - viewModel.selectLocation(result.title) + viewModel.selectLocation(result) } } } @@ -70,6 +70,6 @@ struct LocationSeachView: View { struct LocationSeachView_Previews: PreviewProvider { static var previews: some View { - LocationSeachView(showLocationSearchView: .constant(true)) + LocationSearchView(showLocationSearchView: .constant(true)) } } diff --git a/MarvelUI/Core/LocationSearch/ViewModel/LocationSearchViewModel.swift b/MarvelUI/Core/LocationSearch/ViewModel/LocationSearchViewModel.swift index 5753ae0..993954f 100644 --- a/MarvelUI/Core/LocationSearch/ViewModel/LocationSearchViewModel.swift +++ b/MarvelUI/Core/LocationSearch/ViewModel/LocationSearchViewModel.swift @@ -11,8 +11,10 @@ import MapKit class LocationSearchViewModel: NSObject, ObservableObject { @Published var resuls = [MKLocalSearchCompletion]() - @Published var selectedLocation: String? + @Published var selectedLocationCoordinate: CLLocationCoordinate2D? + private let searchCompleter = MKLocalSearchCompleter() + var queryFragment: String = "" { didSet { searchCompleter.queryFragment = queryFragment @@ -25,9 +27,30 @@ class LocationSearchViewModel: NSObject, ObservableObject { searchCompleter.queryFragment = queryFragment } - func selectLocation(_ location: String) { - self.selectedLocation = location + + // MARK: - Helpers + func selectLocation(_ localSearch: MKLocalSearchCompletion) { + locationSearch(forLocalSearchCompletion: localSearch) { response, error in + if let error = error { + print("DEBUG: Location search error: \(error.localizedDescription)") + return + } + guard let item = response?.mapItems.first else { return } + let coordinate = item.placemark.coordinate + self.selectedLocationCoordinate = coordinate + + print("DEBUG: Location coordinates \(coordinate)") + } } + + func locationSearch(forLocalSearchCompletion localSearch: MKLocalSearchCompletion, + completion: @escaping MKLocalSearch.CompletionHandler) { + let searchRequest = MKLocalSearch.Request() + searchRequest.naturalLanguageQuery = localSearch.title.appending(localSearch.subtitle) + let search = MKLocalSearch(request: searchRequest) + search.start(completionHandler: completion) + } + } // MARK: - MKLocalSearchCompleterDelegate