Is it possible to have a view in the SwiftUI view hierarchy and have its @State persisted, but control when .onAppear() and .onDisappear() are called in some way? This would be connected to visibility, of course. We wouldn't want a visible view that never had onAppear be called.
You can see this behavior in Apple's SwiftUI views, like List, LazyVGrid, TabView, etc.
But rolling this yourself seems more difficult. The .hidden() modifier has .onAppear() called (but removing .hidden() will also reset the view's state). The .opacity(0) modifier doesn't seem to change onAppear.
Context:
The purpose for needing this in the first place is for re-creating TabView on tvOS with a custom tab selection UI. On iOS, you can use a TabView and omit the .tabItem() modifiers and you can show your own tab bar. But on tvOS, the omission of .tabItem() still shows a black pill on the top of the screen. It seems impossible to remove this in tvOS. The paging view style is not a suitable replacement, as focus movement between screens will switch tabs and this is not desired behavior.
The existing TabView will load each page/tab and they'll be initialized and have their state, but .onAppear() is only called when the tab visually appears. And it'll also call .onDisappear() appropriately as well. But I can not re-create the behavior myself.
If there is a way to just use TabView on tvOS and be able to hide the UI for tabs, that is another solution.
Extra notes:
See https://hfossli.medium.com/hiding-and-unhiding-views-in-swiftui-9474a839e5c9. This does happen to implement the behavior properly, but it breaks a lot of other SwiftUI functionality. See some more discussion in https://forums.swift.org/t/replicating-tabview-view-hierarchy-behavior/64872. For instance, Environment is not passed down to the views, because of the UIKit bridging. I was able to manually port over the Environment, but then other SwiftUI things seems to break, and it'll become a game of whack-a-mole to fix everything.
Any insight is appreciated!