How do I save the results of a MKLocalSearch to an Array?

299 views Asked by At

I am experiencing a bit of trouble, while working on my app in SwiftUI. I want to append relevant data, summarized in an object, to an array and return this. While returning the array, I could see by debugging, that it is empty. Debugging in the for loop showed me, that location objects are created and appended, but are not being "saved" in the array. The "mapItems" array on the other hand has lots of members. What am I missing?

Here is the method I came up with:

func searchForLocation(searchTerm: String) -> Array<Location>{
 var locations = [Location]
 let searchReqeust = MKLocalSearch.Request()
 searchRequest.region = region //region is a published variable and is determined before
 searchRequest.naturalLanguageQuery = searchTerm
 
 let search = MKLocalSearch(request: searchRequest)
 search.start{response, error in
 //error handling
 .
 .
 .
 //empty response.mapItems handling
 .
 .
 .     
    for item in response!mapItems{
       let location = createLocationFromItem(item: item)
       locations.append(location)  
    }

  }
   return locations
}

My locations class if following:

class Location: Identifiable{
   var id= UUID()
   var coordinates: CLLocationCoordinate2d

   //And its proper init method
}
1

There are 1 answers

2
workingdog support Ukraine On BEST ANSWER

Your searchForLocation has an asynchronous function inside (search.start{...}), and your code returns before it has finished getting the results. To "wait" for the results use a completion/closure handler, something like this:

func searchForLocation(searchTerm: String, completion: @escaping ([Location]) -> ()) {
     var locations = [Location]()  // <-- here 
    // ....
    
    search.start{response, error in   // <-- here asynchronous function
        //... todo deal with errors, eg return completion([])
        for item in response!mapItems {
           let location = createLocationFromItem(item: item)
           locations.append(location)
        }
        completion(locations) // <- here return when finished
    }
}

and call the function like this:

searchForLocation(searchTerm: "Tokyo") { results in
    print("\(results)")  // <-- here results available, not before
}

I suggest you read-up on how to create and use asynchronous functions, these are important concepts to master to code effectively in Swift.