Description
Description
Hey guys,
first of all, I would like to thank you both for making such a great library. Working with it is a lot of fun! 🥇
I believe, however, that I've found a memory leak when composable architecture is combined with the composable core location dependency in a very specific way. I've prepared a mini demo for you and I would really appreciate it if you'll have time to check it out. It is available here.
To Reproduce
- Download the app
- Launch the app in the simulator
- Allow location updates
- Start simulating location updates, by enabling
Simulator -> Features -> Location -> City Run
- Make sure that you are receiving locations (map is moving)
- Leave it running for a second or two, then take a look at the memory graph
- You'll see that some of the
CLLocation
objects are leaking (image attached)
After investigating, I've found out that if I don't combine reducerA
into the "main" appReducer
, location objects stop leaking. I.e. using just one pulled back child reducer with a core location dependency inside of .combined
block works fine. But as soon as you add another "scoped" reducer, the issue reappears. You can reproduce this "fix" by commenting out the following code.
// MARK: - App Reducer
let appReducer = Reducer<AppState, AppAction, AppEnvironment>.combine(
/*
* Comment out the following reducer
*/
reducerA
.pullback(
state: \.stateA,
action: /AppAction.actionA,
environment: { $0 }
),
reducerB
.pullback(
state: \.stateB,
action: /AppAction.actionB,
environment: { $0 }
)
)
The other strange thing that it seems like it also helps is if you remove the map function from the didUpdateLocations
method in the core location dependency and only use the last location.
Change from:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
subscriber.send(.didUpdateLocations(locations.map(Location.init(rawValue:))))
}
to:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
subscriber.send(.didUpdateLocations(Location.init(rawValue: locations.last!)))
}
Expected behavior
CLLocation
objects should not leak.
Environment
- Xcode Version 12.2 (12B45b)
- Apple Swift version 5.3.1 (swiftlang-1200.0.41 clang-1200.0.32.8)
- macOS Big Sur Version 11.0.1
Thanks for your help in advance. I hope that I am not wasting your time by misusing the library 😄