Bahn-X / swift-composable-navigator

An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind
MIT License
580 stars 25 forks source link

Get notified when a ScreenID is no longer valid? #78

Open ZevEisenberg opened 2 years ago

ZevEisenberg commented 2 years ago

Question

Is it possible to find out when the screen for a particular ScreenID is permanently dismissed? By "permanently" I mean that if the same screen is presented again, it would have a different ScreenID?

Problem description

I'm wrapping an analytics library that has strong ties to UIKit. In particular, it has the concept of a "page" object that is tied to the lifecycle of a UIViewController in memory. I'm trying to replicate this behavior with SwiftUI Views. I can't use onDisappear because that is triggered if a view is covered by a nav push, and in UIKit, views don't get deallocated when they're covered by navigation.

I tried attaching a @StateObject to my views, and having it notify on deinit, but @StateObject seems not to make guarantees about when or if it will deallocate things.

My current thinking is to keep a dictionary that maps ScreenIDs to my analytics page objects, and remove them from the array when a ScreenID becomes invalid. But I would need the composable navigator to tell me when that happens, and I'm not sure if that's possible. I'm thinking something like:

// naming subject to discussion
Navigator.Datasource(root: someRoot, screenIDDidBecomeInvalid: { screenID in
})

I'm not super familiar with the composable navigator's API surface, so maybe there's a better place to put it, but that's the gist of what I'm looking for.

ohitsdaniel commented 2 years ago

Did you try an onDismiss PathBuilder?

https://github.com/Bahn-X/swift-composable-navigator/blob/main/Sources/ComposableNavigator/PathBuilder/PathBuilders/PathBuilder+OnDismiss.swift

I think, that's what you're looking for. It it isn't, let me know. :)

ZevEisenberg commented 2 years ago

This looks promising. Is there somewhere I can stick an onDismiss that will notify me of any dismissal anywhere in the tree? I didn't see an obvious way to do it, and I want to avoid sprinkling onDismiss on all my path builders if possible.

ohitsdaniel commented 2 years ago

You could subscribe to the datasource path publisher and diff on it. There is no guarantee that only a single screen is dismissed at a time (going back to a previous screen, multiple steps before the current one) and the on dismiss view also subscribes above mentioned changes.