I have a form that gets a zip code and passes it to a method. The method looks up the city and state and returns the information as a tuple. The method also has a completion handler so that the rest of the form data isn't saved until the city and state are found.
I moved the function to a view model to keep things in order, but now I'm confused. First of all, the completion handler has to be called before the function returns, even though that seems exactly the opposite of what I want. I want to get the city and state values and then I want to save them through the handler. The second half of my confusion is in the calling of the function. If I assign a variable like cityState
to receive the tuple from my method, the saving happens in a closure which I can't get to! (See Settings View code below.)
I could move everything back to the view where it was working just fine. But I'm trying to understand how MVVM is supposed to work.
Settings View Model
func getCityStateFromPostalCode(zip: String, completion: @escaping () -> ()) -> (String, String) {
let geocoder = CLGeocoder()
var city = ""
var state = ""
geocoder.geocodeAddressString(zip) { (placemarks, error) in
if let placemark = placemarks?[0] {
if placemark.postalCode == zip {
city = placemark.locality!
state = placemark.administrativeArea!
}
}
completion()
}
return (city, state)
}
SettingsView
let settingsVM = SettingsViewModel()
let cityState = settingsVM.getCityStateFromPostalCode(zip: companyZip) {
let newCompany = Company(context: self.moc)
newCompany.id = UUID()
newCompany.city = ?? //can't use cityState here.
newCompany.state = ?? // or here!
}
Return city
and state
in the completion handler, not in the return
:
func getCityStateFromPostalCode(zip: String, completion: @escaping ((String, String)) -> ()) {
let geocoder = CLGeocoder()
var city = ""
var state = ""
geocoder.geocodeAddressString(zip) { (placemarks, error) in
if let placemark = placemarks?[0] {
if placemark.postalCode == zip {
city = placemark.locality!
state = placemark.administrativeArea!
}
}
completion((city, state))
}
}
Then you can do:
settingsVM.getCityStateFromPostalCode(zip: companyZip) { city, state in
let newCompany = Company(context: self.moc)
newCompany.id = UUID()
newCompany.city = city
newCompany.state = state
}