ios – MKLocalSearchCompleter by no means returns options in SwiftUI TextField

0
2
ios – MKLocalSearchCompleter by no means returns options in SwiftUI TextField


I’m constructing a SwiftUI kind that ought to autocomplete road addresses the identical manner Apple Maps does.
I’m utilizing MKLocalSearchCompleter, however its delegate strategies are by no means known as, so no options seem (not even in Xcode’s console). I reproduced the difficulty in a brand-new venture with solely the code under.

What I anticipate

Because the consumer sorts into the TextField, MKLocalSearchCompleter ought to name completer(_:didUpdateResults:), and tackle options ought to be listed under the sphere.

What truly occurs
• The question string updates accurately (verified with print).
• completer(:didUpdateResults:) and completer(:didFailWithError:) are by no means invoked.
• No options are proven.

Minimal reproducible instance

AddressSearchVM.swift

    import SwiftUI
    import MapKit

    last class AddressSearchVM: NSObject, ObservableObject, MKLocalSearchCompleterDelegate {

    @Printed var question = "" {
        didSet {
            // Replace the search fragment at any time when the consumer sorts
            if question.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                completer.queryFragment = ""
                outcomes = []
            } else {
                completer.queryFragment = question
            }
            print("Question modified to: (question)")
        }
    }
    @Printed var outcomes: [MKLocalSearchCompletion] = []

    non-public let completer = MKLocalSearchCompleter()

    override init() {
        tremendous.init()
        completer.delegate = self
        completer.resultTypes = [.address]
        completer.pointOfInterestFilter = .excludingAll

        // Broad area protecting the continental US
        completer.area = MKCoordinateRegion(
            middle: CLLocationCoordinate2D(latitude: 39.8283, longitude: -98.5795),
            span: MKCoordinateSpan(latitudeDelta: 50.0, longitudeDelta: 60.0)
        )
    }

    // MARK: -- MKLocalSearchCompleterDelegate

    func completer(_ completer: MKLocalSearchCompleter,
                   didUpdateResults outcomes: [MKLocalSearchCompletion]) {
        print("Obtained outcomes: (outcomes.map { $0.title })")
        DispatchQueue.fundamental.async {
            self.outcomes = Array(outcomes.prefix(5))
        }
    }

    func completer(_ completer: MKLocalSearchCompleter,
                   didFailWithError error: Error) {
        print("Autocomplete error: (error.localizedDescription)")
        DispatchQueue.fundamental.async {
            self.outcomes = []
        }
    }

    // MARK: -- Helpers

    func clearResults() {
        outcomes = []
        question = ""
    }
  }

ContentView.swift (related half)

struct ContentView: View {
    @StateObject non-public var addressVM = AddressSearchVM()
    @FocusState non-public var focus: Area?
    @State non-public var showingSuggestions = false
    @State non-public var pickupAddress = ""

    enum Area { case tackle }

    var physique: some View {
        Kind {
            Part("Pickup Handle") {
                HStack {
                    Picture(systemName: "mappin.and.ellipse")
                        .foregroundColor(.secondary)

                    TextField("123 Instance St", textual content: $addressVM.question)
                        .targeted($focus, equals: .tackle)
                        .onChange(of: addressVM.question) { _, newValue in
                            showingSuggestions = !newValue.isEmpty && focus == .tackle
                            if newValue.isEmpty { pickupAddress = "" }
                        }
                        .onChange(of: focus) { _, newFocus in
                            showingSuggestions = newFocus == .tackle && !addressVM.question.isEmpty
                        }
                }

                if showingSuggestions && !addressVM.outcomes.isEmpty {
                    VStack(alignment: .main, spacing: 0) {
                        ForEach(addressVM.outcomes, id: .self) { merchandise in
                            Button {
                                let full = merchandise.title + (merchandise.subtitle.isEmpty ? "" : ", (merchandise.subtitle)")
                                pickupAddress = full
                                addressVM.question = full
                                showingSuggestions = false
                                focus = nil
                            } label: {
                                VStack(alignment: .main, spacing: 2) {
                                    Textual content(merchandise.title)
                                    if !merchandise.subtitle.isEmpty {
                                        Textual content(merchandise.subtitle).font(.caption).foregroundColor(.secondary)
                                    }
                                }
                                .padding(.vertical, 8)
                                .body(maxWidth: .infinity, alignment: .main)
                            }
                            .buttonStyle(.plain)

                            if merchandise != addressVM.outcomes.final { Divider() }
                        }
                    }
                }
            }
        }
    }
}

Issues I’ve tried

  1. 1.New clean venture with solely this code → identical conduct.
  2. Completely different simulators (iPhone 14 / 15) and an actual gadget → no change.
  3. Commented out the customized area (let Apple select default) → no change.
  4. Added specific calls to startUpdatingLocation() by way of CLLocationManager to ensure location providers have been lively → nonetheless no delegate callbacks.

Any perception or workaround could be enormously appreciated.
Thanks prematurely!

LEAVE A REPLY

Please enter your comment!
Please enter your name here