TCA holds on to state for longer than expected #3046
-
DescriptionI'm finishing my first app with TCA and was trying to track down a memory leak. While doing so I found an unexpected behaviour in TCA: If a sheet is presented and then dismissed, the associated feature state is not released after the dismiss. Only after the sheet is presented again is the state released. It seems the previous state is being held somewhere within TCA. I've used the SyncUps example to confirm it's not something in my project. Here's a patch for the simple test I made:
Checklist
Expected behaviorI would expect that "DEINIT" is printed when the SyncUpForm is dismissed. Actual behavior"DEINIT" is only printed after the second time the sheet is presented. Steps to reproduce
The Composable Architecture version informationDestination operating systemiOS 17 Xcode version informationVersion 15.3 (15E204a) Swift Compiler version informationswift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
@pfandrade This is a behavior of SwiftUI navigation: when a screen is presented and dismissed, often times the destination view and state are kept around in memory till the next presentation. You can take our vanilla SyncUps app that uses plain old observable models and add this to deinit {
print("DEINIT")
} And the behavior is reproducible in much simpler apps, as well. So I do not think you should depend on the lifetime of objects held in the view graph being tied to the lifetime of views on the screen, and instead you can depend on other, more predictable hooks. Since this isn't a bug in TCA, and is just vanilla SwiftUI behavior, I'm going to convert this to a discussion. |
Beta Was this translation helpful? Give feedback.
@pfandrade This is a behavior of SwiftUI navigation: when a screen is presented and dismissed, often times the destination view and state are kept around in memory till the next presentation. You can take our vanilla SyncUps app that uses plain old observable models and add this to
SyncUpFormModel
and you'll see the same behavior:And the behavior is reproducible in much simpler apps, as well.
So I do not think you should depend on the lifetime of objects held in the view graph being tied to the lifetime of views on the screen, and instead you can depend on other, more predictable hooks.
Since this isn't a bug in TCA, and is just vanilla SwiftUI behavior, I'm …