I am writing an app that uses Reverse Geocoding and the CLGeocoder command. I am using Xcode 11.3 and Swift 5.
The code I am using is stock standard and works ie. I can perform reverse geocoding fine. The issue is that my app calls the reverse geocoded every 5 minutes to report back on the current address - this works absolutely fine.... however, after about 4 days my app no longer works on my test iPhone. When I say no longer works I mean that I click on the icon to open the app and it returns to the IOS. When I run the app on the simulator I can see that about every 5 minutes the memory consumption goes up by 0.01MB, suggesting that maybe after 4 days the containers memory is full and the app stops working properly.
Thus in summary, my question is has anyone else noticed that when using reverse geocoding over a period of time that their apps fail to run properly.
I know its the reverse geocoding as if I don't call the function then the memory consumption stays static.
I know there are limits on the frequency that you can call reversegeolocation - maybe Apple know its leaky and this is why the limit is there (to detract people from doing what I am doing)???
I have attached the entire stock standard code. I have modified it slightly in that I have taken out the frequency element and now made it so you click a button on the screen to trigger the reversegeolocation.... After about 10 clicks you'll see your memory increase, if you keep doing it you'll continue to see the memory increase... (best to try it every 15 - 20 seconds)...
My code:
import Foundation
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
let locationManager:CLLocationManager = CLLocationManager()
var currentLatitude: Double = 37.33030778
var currentLongitude: Double = -122.02896839
@IBOutlet var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
locationManager.delegate = self
print("Running")
}
@IBAction func myButtonPressed(_ sender: Any) {
// Print inside IBACTION
print("Inside IBACTION")
// incease latitude and longitue
currentLatitude = currentLatitude + 0.10
currentLongitude = currentLongitude + 0.10
myReverseGeo()
}
func myReverseGeo() {
let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)
let geocoder: CLGeocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
if error != nil {
let errorString = String(describing: error?.localizedDescription)
print("Reverse Geocoding failed")
print(errorString)
return
}
let placemark = placemarks! as [CLPlacemark]
if placemark.count > 0 {
let placemark = placemarks![0]
let eventCity = placemark.locality
let eventState = placemark.subAdministrativeArea
let eventCountry = placemark.country
print(eventCity!)
print(eventState!)
print(eventCountry!)
}
})
}
}
Any ideas folks on how to stop the memory leak (other than not use reverse geocoding)???


I don’t think your memory issues are coming from this routine. I ran it for 144 iterations (for 12 minutes, firing ever 5 seconds; equivalent to running it for 12 hours every 5 minutes) and saw no appreciable memory growth:
(Each of those “points of interest” signposts mark a reverse geocode request.)
A few observations, though:
Rather than instantiating a new
CLGeocoderfor every request, I’d instantiate one, and perform repeatedreverseGeocodeLocationcall with that one instance.Regarding limitations on
CLGeocoder, the main limitation is you cannot perform simultaneous geocode requests (and if you attempt to do so, it just fails with an error).Re why you’re getting memory growth, I can’t comment on that, because I cannot reproduce the behavior you describe. Perhaps you have some debugging options turned on (malloc stack traces, zombies, etc.). That would yield the behavior you describe. Turn off all optional memory diagnostics and perform a release build.
If memory is growing, there are two tools that are useful:
The “Debug Memory Graph” will show you objects that have been created and you can look at what strong references have been established where.
If you profile the app using the “Leaks” tool (which also provides the “Allocations” tool) in Instruments, you can examine exactly what allocations have been created where.
For more information, see How to debug memory leaks when Leaks instrument does not show them?
Generally, if we’re looking for updates to user locations, the visits service and the significant change service are more efficient ways of doing this. Why drain the user’s battery by doing this every five minutes, when there are going to be long spans where the user doesn’t move. Let the device tell your app when the user moves rather than polling constantly.
It’s not terribly relevant, but this is my code that generated the above image:
With