Reverse geocoding should not occur multiple times per session #462
Labels
Concurrency
Swift structured concurrency & Swift6 data race prevention
Enhancement
New feature or request
If the user scrolls up and down within the
Clubs and Museums
screen, any map that gets displayed triggers (.onAppear
) an asynchronous call toreverseGeocode
. This fetches localized Town and Country strings that match the current language setting of the device.This use of
onAppear
means the app can send multiple identical requests to Apple's mapping server. Even once is a bit more than needed: the results are stored in Core Data. But recomputing.onAppear
means that any club/museum coordinate updates or a change in the device's language setting are automatically handled just before the data is displayed.Drawbacks of multiple calls to
reverseGeocode
Alternative solutions
Store (in volatile static dictionary?) the list of clubs that have already been reverseGeocoded in this session.
⇒ API usage is one call per club per session.
Verdict: not enough benefit for the effort?
Store (Core Data) the date when localizedTown and localizedCountry were last refreshed. Until date+N days, we assume any available translations are stil valid, and an API call is saved.
Needs special handling at startup if the current locale matches the previous locale (UserData). If there is no match, all translations stored in Core Data are invalidated (by changing the date or setting the strings to nil).
Needs special handling (in the unlikely case) that the coordinates of an existing club are changed: also invalidate that record.
The locale/coordinate guarding should handle normal updating; the date trick is just to handle sever-side data changes.
Multiple clubs can get invalidated on the same day if they were first loaded/viewed on the same day. This can be handled by spreading the load across a few days (
Int.random(0...10)
)⇒ API usage is one call per club per N days. Say N=100 days.
Same as 2, but without the date-based safety net.
⇒ API usage is one call per club (unless an update is needed, close to absolute minimum).
Can serve as intermediate step to get to 2.
Same as 2, but with with the strings stored in UserData instead of CoreData organization objects.
Implement as a cache on the reverseGeocode(coordinates: coordinates, locale) request, without caring about the Organization being processed. Cache can be stored as a dictionary in UserDefaults. For 1000 organizations and a user who only uses a single language, this is a dictionary with 1000 structs with 5 fields: language, latitude, longitude, localizedTown, localizedCountry.
If needed, nearby locations (say 250m) can result in cache hits. This will occasionally save API calls if there are multiple organizations in the same building, or if a coordinate shifts slightly (e.g. extra digit of precision added).
⇒ API usage is one call per club (unless an update is needed, close to absolute minimum).
Store in CoreData entity the language(s) for which the localized Town/Country was computed. If new language appears, recompute. If coordinates change, force a recompute by setting the language to nil or a dummy language. So this requires only 1 stored field.
⇒ API usage is one call per club (unless an update is needed, close to absolute minimum). This is absolute minimum if multiple languages are "cached".
Steps to get to 2nd alternative
The text was updated successfully, but these errors were encountered: