Retain cycles with CLLocationManager
I was implementing a location services functionality when I (luckily) noticed that my class wasn’t deallocating. I suspected my own code, of course, but a little bit of digging showed that the problem actually seemed to be in CLLocationManager
, specifically it seems to retain the delegate after calling requestLocation()
or startUpdatingLocation()
.
Test Playground
I can easily reproduce it every time and everything seems to be pointing to the delegate being retained while it shouldn’t since it’s marked as weak
. Example:
class TestClass: NSObject, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
init(request: Bool) {
super.init()
locationManager.delegate = self
if request {
locationManager.requestLocation()
// or locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {}
}
weak var obj1: TestClass?
weak var obj2: TestClass?
func createInstances() {
let instance1 = TestClass(request: true)
obj1 = instance1
let instance2 = TestClass(request: false)
obj2 = instance2
}
createInstances()
print("obj1 deallocated: \(obj1 == nil)")
print("obj2 deallocated: \(obj2 == nil)")
This class creates a CLLocationManager
, sets the delegate to self and requests location (if we tell it too). Now, simply testing 2 instances of this class (one of which doesn’t request location) shows that obj1
is not deallocated while obj2
is.
I’ve filled a bug with Apple (FB8943197) so hopefully we can get this resolved soon as it can cause pretty nasty memory leaks.