I'm trying to implement address completion in a React Native application by using a native module that uses a MKLocalSearchCompleter
. It's a simple enough class with straightforward delegate methods, but I can't seem to get results from my app. Even running the associated Unit Tests won't work, and I'm not sure why.
Whats happening is that I set the .queryFragment
property to my partial string, which should automatically kick off the search which informs my delegate when it's completed or if there's an error. I set the delegate appropriately before making the request, but my delegate completerDidUpdateResults(_ completer: MKLocalSearchCompleter)
or completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error)
methods never get called.
The .isSearching
property is set to false after initialization, and when I set the .queryFragment
is becomes true, so it seems to be working internally. If I create a new project and drag in the exact same class and unit tests the test runs fine and I get my results with no problems and the test completes in ~0.25 seconds, but in my actual Application project the test hits the 30 second timeout and fails before I get a response.
The only other question I could find on this problem was a Apple Developer Forum question explaining my same situation with no responses from September
Here's my code and tests:
class AddressUtils: NSObject, MKLocalSearchCompleterDelegate {
let searchCompleter = MKLocalSearchCompleter()
var results: [MKLocalSearchCompletion]?
var onSuggestionsReceived: (([String]) -> Void)?
public override init() {
super.init()
searchCompleter.delegate = self
}
public func getAddressSuggestions(address: String!, completion: @escaping ([String]) -> Void) {
self.onSuggestionsReceived = completion
searchCompleter.queryFragment = address
if searchCompleter.isSearching {
print("Searching") // Prints
}
}
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
self.results = completer.results
let results = completer.results.flatMap { (result) -> String? in
return result.title + " " + result.subtitle
}
onSuggestionsReceived?(results)
}
func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
onSuggestionsReceived?([])
}
}
class UtilityTests: XCTestCase {
func testAddressAutocomplete() {
let expectation = self.expectation(description: "Perform search")
let query = "11 Farns"
let utils = AddressUtils()
utils.getAddressSuggestions(address: query) { (results) in
expectation.fulfill()
}
wait(for: [expectation], timeout: 30)
}
}
Not sure if you ever solved this problem but I had the same issue. Managed to fix by ensuring that queryFragment
is only set not the main thread.
private let completer: MKLocalSearchCompleter
DispatchQueue.main.async { [weak self] in
self?.completer.queryFragment = newValue
}
I was able to get this working after a few days of playing around, but it seems to have been related to the tests themselves, rather than with the actual API or implementation. So much for Test-Driven-Development I guess. The issue was that our test target was added separately and was being run as a separate target with its own scheme, rather than by using the 'Test' configuration from the main scheme. Not entirely sure why that made a difference, but that's my best advice if you're stuck on this issue like I was.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.