├── AddressAutocomplete ├── Assets.xcassets │ ├── Contents.json │ ├── AccentColor.colorset │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── Models │ ├── AddressResult.swift │ └── AnnotationItem.swift ├── AddressAutocompleteApp.swift ├── Content │ ├── AddressRow.swift │ ├── ClearButton.swift │ ├── ContentViewModel.swift │ └── ContentView.swift └── Map │ ├── MapView.swift │ └── MapViewModel.swift ├── AddressAutocomplete.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcuserdata │ └── maxkalik.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist └── project.pbxproj ├── README.md └── .gitignore /AddressAutocomplete/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AddressAutocomplete/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AddressAutocomplete.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AddressAutocomplete/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /AddressAutocomplete.xcodeproj/xcuserdata/maxkalik.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /AddressAutocomplete/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Address autocomplete using SwiftUI and MapKit 2 | 3 | Article: https://medium.com/gitconnected/implementing-address-autocomplete-using-swiftui-and-mapkit-c094d08cda24 4 | 5 | ![1_xPhqFxM3gXkOHtpJzVQo1Q](https://user-images.githubusercontent.com/30437727/221377625-17ea4095-f8b3-411b-a164-2e1f95d3d030.gif) 6 | -------------------------------------------------------------------------------- /AddressAutocomplete/Models/AddressResult.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddressResult.swift 3 | // AddressAutocomplete 4 | // 5 | // Created by Maksim Kalik on 11/29/22. 6 | // 7 | 8 | import Foundation 9 | 10 | struct AddressResult: Identifiable { 11 | let id = UUID() 12 | let title: String 13 | let subtitle: String 14 | } 15 | -------------------------------------------------------------------------------- /AddressAutocomplete.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AddressAutocomplete/AddressAutocompleteApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddressAutocompleteApp.swift 3 | // AddressAutocomplete 4 | // 5 | // Created by Maksim Kalik on 11/27/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct AddressAutocompleteApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView(viewModel: ContentViewModel()) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AddressAutocomplete/Models/AnnotationItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnnotationItem.swift 3 | // AddressAutocomplete 4 | // 5 | // Created by Maksim Kalik on 11/29/22. 6 | // 7 | 8 | import Foundation 9 | import MapKit 10 | 11 | struct AnnotationItem: Identifiable { 12 | let id = UUID() 13 | let latitude: Double 14 | let longitude: Double 15 | var coordinate: CLLocationCoordinate2D { 16 | CLLocationCoordinate2D(latitude: latitude, longitude: longitude) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /AddressAutocomplete.xcodeproj/xcuserdata/maxkalik.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AddressAutocomplete.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /AddressAutocomplete/Content/AddressRow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddressRow.swift 3 | // AddressAutocomplete 4 | // 5 | // Created by Maksim Kalik on 11/30/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AddressRow: View { 11 | 12 | let address: AddressResult 13 | 14 | var body: some View { 15 | NavigationLink { 16 | MapView(address: address) 17 | } label: { 18 | VStack(alignment: .leading) { 19 | Text(address.title) 20 | Text(address.subtitle) 21 | .font(.caption) 22 | } 23 | } 24 | .padding(.bottom, 2) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /AddressAutocomplete/Content/ClearButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ClearButton.swift 3 | // AddressAutocomplete 4 | // 5 | // Created by Maksim Kalik on 11/30/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ClearButton: View { 11 | 12 | @Binding var text: String 13 | 14 | var body: some View { 15 | if text.isEmpty == false { 16 | HStack { 17 | Spacer() 18 | Button { 19 | text = "" 20 | } label: { 21 | Image(systemName: "multiply.circle.fill") 22 | .foregroundColor(Color(red: 0.7, green: 0.7, blue: 0.7)) 23 | } 24 | .foregroundColor(.secondary) 25 | } 26 | } else { 27 | EmptyView() 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /AddressAutocomplete/Map/MapView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapView.swift 3 | // AddressAutocomplete 4 | // 5 | // Created by Maksim Kalik on 11/27/22. 6 | // 7 | 8 | import SwiftUI 9 | import MapKit 10 | 11 | struct MapView: View { 12 | 13 | @StateObject private var viewModel = MapViewModel() 14 | 15 | private let address: AddressResult 16 | 17 | init(address: AddressResult) { 18 | self.address = address 19 | } 20 | 21 | var body: some View { 22 | Map( 23 | coordinateRegion: $viewModel.region, 24 | annotationItems: viewModel.annotationItems, 25 | annotationContent: { item in 26 | MapMarker(coordinate: item.coordinate) 27 | } 28 | ) 29 | .onAppear { 30 | self.viewModel.getPlace(from: address) 31 | } 32 | .edgesIgnoringSafeArea(.bottom) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /AddressAutocomplete/Map/MapViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapViewModel.swift 3 | // AddressAutocomplete 4 | // 5 | // Created by Maksim Kalik on 11/28/22. 6 | // 7 | 8 | import Foundation 9 | import MapKit 10 | 11 | class MapViewModel: ObservableObject { 12 | 13 | @Published var region = MKCoordinateRegion() 14 | @Published var annotationItems: [AnnotationItem] = [] 15 | 16 | func getPlace(from address: AddressResult) { 17 | let request = MKLocalSearch.Request() 18 | let title = address.title 19 | let subTitle = address.subtitle 20 | 21 | request.naturalLanguageQuery = subTitle.contains(title) 22 | ? subTitle : title + ", " + subTitle 23 | 24 | Task { 25 | let response = try await MKLocalSearch(request: request).start() 26 | await MainActor.run { 27 | self.annotationItems = response.mapItems.map { 28 | AnnotationItem( 29 | latitude: $0.placemark.coordinate.latitude, 30 | longitude: $0.placemark.coordinate.longitude 31 | ) 32 | } 33 | 34 | self.region = response.boundingRegion 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /AddressAutocomplete/Content/ContentViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewModel.swift 3 | // AddressAutocomplete 4 | // 5 | // Created by Maksim Kalik on 11/27/22. 6 | // 7 | 8 | import Foundation 9 | import MapKit 10 | 11 | class ContentViewModel: NSObject, ObservableObject { 12 | 13 | @Published private(set) var results: Array = [] 14 | @Published var searchableText = "" 15 | 16 | private lazy var localSearchCompleter: MKLocalSearchCompleter = { 17 | let completer = MKLocalSearchCompleter() 18 | completer.delegate = self 19 | return completer 20 | }() 21 | 22 | func searchAddress(_ searchableText: String) { 23 | guard searchableText.isEmpty == false else { return } 24 | localSearchCompleter.queryFragment = searchableText 25 | } 26 | } 27 | 28 | extension ContentViewModel: MKLocalSearchCompleterDelegate { 29 | func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) { 30 | Task { @MainActor in 31 | results = completer.results.map { 32 | AddressResult(title: $0.title, subtitle: $0.subtitle) 33 | } 34 | } 35 | } 36 | 37 | func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) { 38 | print(error) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /AddressAutocomplete/Content/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // AddressAutocomplete 4 | // 5 | // Created by Maksim Kalik on 11/27/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | 12 | @StateObject var viewModel: ContentViewModel 13 | @FocusState private var isFocusedTextField: Bool 14 | 15 | var body: some View { 16 | NavigationView { 17 | VStack(alignment: .leading, spacing: 0) { 18 | TextField("Type address", text: $viewModel.searchableText) 19 | .padding() 20 | .autocorrectionDisabled() 21 | .focused($isFocusedTextField) 22 | .font(.title) 23 | .onReceive( 24 | viewModel.$searchableText.debounce( 25 | for: .seconds(1), 26 | scheduler: DispatchQueue.main 27 | ) 28 | ) { 29 | viewModel.searchAddress($0) 30 | } 31 | .background(Color.init(uiColor: .systemBackground)) 32 | .overlay { 33 | ClearButton(text: $viewModel.searchableText) 34 | .padding(.trailing) 35 | .padding(.top, 8) 36 | } 37 | .onAppear { 38 | isFocusedTextField = true 39 | } 40 | List(self.viewModel.results) { address in 41 | AddressRow(address: address) 42 | .listRowBackground(backgroundColor) 43 | } 44 | .listStyle(.plain) 45 | .scrollContentBackground(.hidden) 46 | } 47 | .background(backgroundColor) 48 | .edgesIgnoringSafeArea(.bottom) 49 | } 50 | } 51 | 52 | var backgroundColor: Color = Color.init(uiColor: .systemGray6) 53 | } 54 | 55 | struct ContentView_Previews: PreviewProvider { 56 | static var previews: some View { 57 | ContentView(viewModel: ContentViewModel()) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 9 | *.xcscmblueprint 10 | *.xccheckout 11 | 12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 13 | build/ 14 | DerivedData/ 15 | *.moved-aside 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | 28 | ## App packaging 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | # Package.pins 42 | # Package.resolved 43 | # *.xcodeproj 44 | # 45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 46 | # hence it is not needed unless you have added a package configuration file to your project 47 | # .swiftpm 48 | 49 | .build/ 50 | 51 | # CocoaPods 52 | # 53 | # We recommend against adding the Pods directory to your .gitignore. However 54 | # you should judge for yourself, the pros and cons are mentioned at: 55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 56 | # 57 | # Pods/ 58 | # 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | # *.xcworkspace 61 | 62 | # Carthage 63 | # 64 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 65 | # Carthage/Checkouts 66 | 67 | Carthage/Build/ 68 | 69 | # Accio dependency management 70 | Dependencies/ 71 | .accio/ 72 | 73 | # fastlane 74 | # 75 | # It is recommended to not store the screenshots in the git repo. 76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 77 | # For more information about the recommended setup visit: 78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 79 | 80 | fastlane/report.xml 81 | fastlane/Preview.html 82 | fastlane/screenshots/**/*.png 83 | fastlane/test_output 84 | 85 | # Code Injection 86 | # 87 | # After new code Injection tools there's a generated folder /iOSInjectionProject 88 | # https://github.com/johnno1962/injectionforxcode 89 | 90 | iOSInjectionProject/ 91 | -------------------------------------------------------------------------------- /AddressAutocomplete.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 11E78E8B29376CB3002F50A8 /* ClearButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11E78E8A29376CB3002F50A8 /* ClearButton.swift */; }; 11 | 11E78E8D29376F2C002F50A8 /* AddressRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11E78E8C29376F2C002F50A8 /* AddressRow.swift */; }; 12 | 11F42B8C2934084D0097ABB8 /* AddressAutocompleteApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11F42B8B2934084D0097ABB8 /* AddressAutocompleteApp.swift */; }; 13 | 11F42B8E2934084D0097ABB8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11F42B8D2934084D0097ABB8 /* ContentView.swift */; }; 14 | 11F42B902934084E0097ABB8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 11F42B8F2934084E0097ABB8 /* Assets.xcassets */; }; 15 | 11F42B932934084E0097ABB8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 11F42B922934084E0097ABB8 /* Preview Assets.xcassets */; }; 16 | 11F42B9A293408780097ABB8 /* ContentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11F42B99293408780097ABB8 /* ContentViewModel.swift */; }; 17 | 11F42B9C29341EDB0097ABB8 /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11F42B9B29341EDB0097ABB8 /* MapView.swift */; }; 18 | 11F42B9E293514150097ABB8 /* MapViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11F42B9D293514150097ABB8 /* MapViewModel.swift */; }; 19 | 11FDDA6329365FBE009499C4 /* AnnotationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11FDDA6229365FBE009499C4 /* AnnotationItem.swift */; }; 20 | 11FDDA6529365FDA009499C4 /* AddressResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11FDDA6429365FDA009499C4 /* AddressResult.swift */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 11E78E8A29376CB3002F50A8 /* ClearButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearButton.swift; sourceTree = ""; }; 25 | 11E78E8C29376F2C002F50A8 /* AddressRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressRow.swift; sourceTree = ""; }; 26 | 11F42B882934084D0097ABB8 /* AddressAutocomplete.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AddressAutocomplete.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 11F42B8B2934084D0097ABB8 /* AddressAutocompleteApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressAutocompleteApp.swift; sourceTree = ""; }; 28 | 11F42B8D2934084D0097ABB8 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 29 | 11F42B8F2934084E0097ABB8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 11F42B922934084E0097ABB8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 31 | 11F42B99293408780097ABB8 /* ContentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewModel.swift; sourceTree = ""; }; 32 | 11F42B9B29341EDB0097ABB8 /* MapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = ""; }; 33 | 11F42B9D293514150097ABB8 /* MapViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewModel.swift; sourceTree = ""; }; 34 | 11FDDA6229365FBE009499C4 /* AnnotationItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnnotationItem.swift; sourceTree = ""; }; 35 | 11FDDA6429365FDA009499C4 /* AddressResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressResult.swift; sourceTree = ""; }; 36 | /* End PBXFileReference section */ 37 | 38 | /* Begin PBXFrameworksBuildPhase section */ 39 | 11F42B852934084D0097ABB8 /* Frameworks */ = { 40 | isa = PBXFrameworksBuildPhase; 41 | buildActionMask = 2147483647; 42 | files = ( 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXFrameworksBuildPhase section */ 47 | 48 | /* Begin PBXGroup section */ 49 | 11F42B7F2934084D0097ABB8 = { 50 | isa = PBXGroup; 51 | children = ( 52 | 11F42B8A2934084D0097ABB8 /* AddressAutocomplete */, 53 | 11F42B892934084D0097ABB8 /* Products */, 54 | ); 55 | sourceTree = ""; 56 | }; 57 | 11F42B892934084D0097ABB8 /* Products */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 11F42B882934084D0097ABB8 /* AddressAutocomplete.app */, 61 | ); 62 | name = Products; 63 | sourceTree = ""; 64 | }; 65 | 11F42B8A2934084D0097ABB8 /* AddressAutocomplete */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 11FDDA6129365FA1009499C4 /* Models */, 69 | 11FDDA6029365F98009499C4 /* Map */, 70 | 11FDDA5F29365F8C009499C4 /* Content */, 71 | 11F42B8B2934084D0097ABB8 /* AddressAutocompleteApp.swift */, 72 | 11F42B8F2934084E0097ABB8 /* Assets.xcassets */, 73 | 11F42B912934084E0097ABB8 /* Preview Content */, 74 | ); 75 | path = AddressAutocomplete; 76 | sourceTree = ""; 77 | }; 78 | 11F42B912934084E0097ABB8 /* Preview Content */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 11F42B922934084E0097ABB8 /* Preview Assets.xcassets */, 82 | ); 83 | path = "Preview Content"; 84 | sourceTree = ""; 85 | }; 86 | 11FDDA5F29365F8C009499C4 /* Content */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 11F42B99293408780097ABB8 /* ContentViewModel.swift */, 90 | 11F42B8D2934084D0097ABB8 /* ContentView.swift */, 91 | 11E78E8C29376F2C002F50A8 /* AddressRow.swift */, 92 | 11E78E8A29376CB3002F50A8 /* ClearButton.swift */, 93 | ); 94 | path = Content; 95 | sourceTree = ""; 96 | }; 97 | 11FDDA6029365F98009499C4 /* Map */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 11F42B9D293514150097ABB8 /* MapViewModel.swift */, 101 | 11F42B9B29341EDB0097ABB8 /* MapView.swift */, 102 | ); 103 | path = Map; 104 | sourceTree = ""; 105 | }; 106 | 11FDDA6129365FA1009499C4 /* Models */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 11FDDA6229365FBE009499C4 /* AnnotationItem.swift */, 110 | 11FDDA6429365FDA009499C4 /* AddressResult.swift */, 111 | ); 112 | path = Models; 113 | sourceTree = ""; 114 | }; 115 | /* End PBXGroup section */ 116 | 117 | /* Begin PBXNativeTarget section */ 118 | 11F42B872934084D0097ABB8 /* AddressAutocomplete */ = { 119 | isa = PBXNativeTarget; 120 | buildConfigurationList = 11F42B962934084E0097ABB8 /* Build configuration list for PBXNativeTarget "AddressAutocomplete" */; 121 | buildPhases = ( 122 | 11F42B842934084D0097ABB8 /* Sources */, 123 | 11F42B852934084D0097ABB8 /* Frameworks */, 124 | 11F42B862934084D0097ABB8 /* Resources */, 125 | ); 126 | buildRules = ( 127 | ); 128 | dependencies = ( 129 | ); 130 | name = AddressAutocomplete; 131 | productName = AddressAutocomplete; 132 | productReference = 11F42B882934084D0097ABB8 /* AddressAutocomplete.app */; 133 | productType = "com.apple.product-type.application"; 134 | }; 135 | /* End PBXNativeTarget section */ 136 | 137 | /* Begin PBXProject section */ 138 | 11F42B802934084D0097ABB8 /* Project object */ = { 139 | isa = PBXProject; 140 | attributes = { 141 | BuildIndependentTargetsInParallel = 1; 142 | LastSwiftUpdateCheck = 1400; 143 | LastUpgradeCheck = 1400; 144 | TargetAttributes = { 145 | 11F42B872934084D0097ABB8 = { 146 | CreatedOnToolsVersion = 14.0; 147 | }; 148 | }; 149 | }; 150 | buildConfigurationList = 11F42B832934084D0097ABB8 /* Build configuration list for PBXProject "AddressAutocomplete" */; 151 | compatibilityVersion = "Xcode 14.0"; 152 | developmentRegion = en; 153 | hasScannedForEncodings = 0; 154 | knownRegions = ( 155 | en, 156 | Base, 157 | ); 158 | mainGroup = 11F42B7F2934084D0097ABB8; 159 | productRefGroup = 11F42B892934084D0097ABB8 /* Products */; 160 | projectDirPath = ""; 161 | projectRoot = ""; 162 | targets = ( 163 | 11F42B872934084D0097ABB8 /* AddressAutocomplete */, 164 | ); 165 | }; 166 | /* End PBXProject section */ 167 | 168 | /* Begin PBXResourcesBuildPhase section */ 169 | 11F42B862934084D0097ABB8 /* Resources */ = { 170 | isa = PBXResourcesBuildPhase; 171 | buildActionMask = 2147483647; 172 | files = ( 173 | 11F42B932934084E0097ABB8 /* Preview Assets.xcassets in Resources */, 174 | 11F42B902934084E0097ABB8 /* Assets.xcassets in Resources */, 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | }; 178 | /* End PBXResourcesBuildPhase section */ 179 | 180 | /* Begin PBXSourcesBuildPhase section */ 181 | 11F42B842934084D0097ABB8 /* Sources */ = { 182 | isa = PBXSourcesBuildPhase; 183 | buildActionMask = 2147483647; 184 | files = ( 185 | 11F42B8E2934084D0097ABB8 /* ContentView.swift in Sources */, 186 | 11F42B9E293514150097ABB8 /* MapViewModel.swift in Sources */, 187 | 11F42B9C29341EDB0097ABB8 /* MapView.swift in Sources */, 188 | 11F42B9A293408780097ABB8 /* ContentViewModel.swift in Sources */, 189 | 11F42B8C2934084D0097ABB8 /* AddressAutocompleteApp.swift in Sources */, 190 | 11E78E8D29376F2C002F50A8 /* AddressRow.swift in Sources */, 191 | 11FDDA6529365FDA009499C4 /* AddressResult.swift in Sources */, 192 | 11FDDA6329365FBE009499C4 /* AnnotationItem.swift in Sources */, 193 | 11E78E8B29376CB3002F50A8 /* ClearButton.swift in Sources */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXSourcesBuildPhase section */ 198 | 199 | /* Begin XCBuildConfiguration section */ 200 | 11F42B942934084E0097ABB8 /* Debug */ = { 201 | isa = XCBuildConfiguration; 202 | buildSettings = { 203 | ALWAYS_SEARCH_USER_PATHS = NO; 204 | CLANG_ANALYZER_NONNULL = YES; 205 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 206 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 207 | CLANG_ENABLE_MODULES = YES; 208 | CLANG_ENABLE_OBJC_ARC = YES; 209 | CLANG_ENABLE_OBJC_WEAK = YES; 210 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 211 | CLANG_WARN_BOOL_CONVERSION = YES; 212 | CLANG_WARN_COMMA = YES; 213 | CLANG_WARN_CONSTANT_CONVERSION = YES; 214 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 215 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 216 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 217 | CLANG_WARN_EMPTY_BODY = YES; 218 | CLANG_WARN_ENUM_CONVERSION = YES; 219 | CLANG_WARN_INFINITE_RECURSION = YES; 220 | CLANG_WARN_INT_CONVERSION = YES; 221 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 222 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 223 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 224 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 225 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 226 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 227 | CLANG_WARN_STRICT_PROTOTYPES = YES; 228 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 229 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 230 | CLANG_WARN_UNREACHABLE_CODE = YES; 231 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 232 | COPY_PHASE_STRIP = NO; 233 | DEBUG_INFORMATION_FORMAT = dwarf; 234 | ENABLE_STRICT_OBJC_MSGSEND = YES; 235 | ENABLE_TESTABILITY = YES; 236 | GCC_C_LANGUAGE_STANDARD = gnu11; 237 | GCC_DYNAMIC_NO_PIC = NO; 238 | GCC_NO_COMMON_BLOCKS = YES; 239 | GCC_OPTIMIZATION_LEVEL = 0; 240 | GCC_PREPROCESSOR_DEFINITIONS = ( 241 | "DEBUG=1", 242 | "$(inherited)", 243 | ); 244 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 245 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 246 | GCC_WARN_UNDECLARED_SELECTOR = YES; 247 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 248 | GCC_WARN_UNUSED_FUNCTION = YES; 249 | GCC_WARN_UNUSED_VARIABLE = YES; 250 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 251 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 252 | MTL_FAST_MATH = YES; 253 | ONLY_ACTIVE_ARCH = YES; 254 | SDKROOT = iphoneos; 255 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 256 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 257 | }; 258 | name = Debug; 259 | }; 260 | 11F42B952934084E0097ABB8 /* Release */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ALWAYS_SEARCH_USER_PATHS = NO; 264 | CLANG_ANALYZER_NONNULL = YES; 265 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 266 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 267 | CLANG_ENABLE_MODULES = YES; 268 | CLANG_ENABLE_OBJC_ARC = YES; 269 | CLANG_ENABLE_OBJC_WEAK = YES; 270 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 271 | CLANG_WARN_BOOL_CONVERSION = YES; 272 | CLANG_WARN_COMMA = YES; 273 | CLANG_WARN_CONSTANT_CONVERSION = YES; 274 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 275 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 276 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 277 | CLANG_WARN_EMPTY_BODY = YES; 278 | CLANG_WARN_ENUM_CONVERSION = YES; 279 | CLANG_WARN_INFINITE_RECURSION = YES; 280 | CLANG_WARN_INT_CONVERSION = YES; 281 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 282 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 283 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 284 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 285 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 286 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 287 | CLANG_WARN_STRICT_PROTOTYPES = YES; 288 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 289 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 290 | CLANG_WARN_UNREACHABLE_CODE = YES; 291 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 292 | COPY_PHASE_STRIP = NO; 293 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 294 | ENABLE_NS_ASSERTIONS = NO; 295 | ENABLE_STRICT_OBJC_MSGSEND = YES; 296 | GCC_C_LANGUAGE_STANDARD = gnu11; 297 | GCC_NO_COMMON_BLOCKS = YES; 298 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 299 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 300 | GCC_WARN_UNDECLARED_SELECTOR = YES; 301 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 302 | GCC_WARN_UNUSED_FUNCTION = YES; 303 | GCC_WARN_UNUSED_VARIABLE = YES; 304 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 305 | MTL_ENABLE_DEBUG_INFO = NO; 306 | MTL_FAST_MATH = YES; 307 | SDKROOT = iphoneos; 308 | SWIFT_COMPILATION_MODE = wholemodule; 309 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 310 | VALIDATE_PRODUCT = YES; 311 | }; 312 | name = Release; 313 | }; 314 | 11F42B972934084E0097ABB8 /* Debug */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 318 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 319 | CODE_SIGN_STYLE = Automatic; 320 | CURRENT_PROJECT_VERSION = 1; 321 | DEVELOPMENT_ASSET_PATHS = "\"AddressAutocomplete/Preview Content\""; 322 | DEVELOPMENT_TEAM = P353H6D448; 323 | ENABLE_PREVIEWS = YES; 324 | GENERATE_INFOPLIST_FILE = YES; 325 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 326 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 327 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 328 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 329 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 330 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 331 | LD_RUNPATH_SEARCH_PATHS = ( 332 | "$(inherited)", 333 | "@executable_path/Frameworks", 334 | ); 335 | MARKETING_VERSION = 1.0; 336 | PRODUCT_BUNDLE_IDENTIFIER = com.maxkalik.AddressAutocomplete; 337 | PRODUCT_NAME = "$(TARGET_NAME)"; 338 | SWIFT_EMIT_LOC_STRINGS = YES; 339 | SWIFT_VERSION = 5.0; 340 | TARGETED_DEVICE_FAMILY = "1,2"; 341 | }; 342 | name = Debug; 343 | }; 344 | 11F42B982934084E0097ABB8 /* Release */ = { 345 | isa = XCBuildConfiguration; 346 | buildSettings = { 347 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 348 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 349 | CODE_SIGN_STYLE = Automatic; 350 | CURRENT_PROJECT_VERSION = 1; 351 | DEVELOPMENT_ASSET_PATHS = "\"AddressAutocomplete/Preview Content\""; 352 | DEVELOPMENT_TEAM = P353H6D448; 353 | ENABLE_PREVIEWS = YES; 354 | GENERATE_INFOPLIST_FILE = YES; 355 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 356 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 357 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 358 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 359 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 360 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 361 | LD_RUNPATH_SEARCH_PATHS = ( 362 | "$(inherited)", 363 | "@executable_path/Frameworks", 364 | ); 365 | MARKETING_VERSION = 1.0; 366 | PRODUCT_BUNDLE_IDENTIFIER = com.maxkalik.AddressAutocomplete; 367 | PRODUCT_NAME = "$(TARGET_NAME)"; 368 | SWIFT_EMIT_LOC_STRINGS = YES; 369 | SWIFT_VERSION = 5.0; 370 | TARGETED_DEVICE_FAMILY = "1,2"; 371 | }; 372 | name = Release; 373 | }; 374 | /* End XCBuildConfiguration section */ 375 | 376 | /* Begin XCConfigurationList section */ 377 | 11F42B832934084D0097ABB8 /* Build configuration list for PBXProject "AddressAutocomplete" */ = { 378 | isa = XCConfigurationList; 379 | buildConfigurations = ( 380 | 11F42B942934084E0097ABB8 /* Debug */, 381 | 11F42B952934084E0097ABB8 /* Release */, 382 | ); 383 | defaultConfigurationIsVisible = 0; 384 | defaultConfigurationName = Release; 385 | }; 386 | 11F42B962934084E0097ABB8 /* Build configuration list for PBXNativeTarget "AddressAutocomplete" */ = { 387 | isa = XCConfigurationList; 388 | buildConfigurations = ( 389 | 11F42B972934084E0097ABB8 /* Debug */, 390 | 11F42B982934084E0097ABB8 /* Release */, 391 | ); 392 | defaultConfigurationIsVisible = 0; 393 | defaultConfigurationName = Release; 394 | }; 395 | /* End XCConfigurationList section */ 396 | }; 397 | rootObject = 11F42B802934084D0097ABB8 /* Project object */; 398 | } 399 | --------------------------------------------------------------------------------