Infinite loop using NavigationStack

Hello.

I've seen some other posts about NavigationStack, but my variation seems a little different.

FYI, I have not migrated from ObservableObject to Observable yet. However, having a path in either seems to be a factor in this issue.

My code has no issues when built with Xcode 15.

When built with Xcode 16 I keep hitting scenarios where the .onAppear for my first tab gets called over and over again endlessly.

If I go to my second tab, which uses a NavStack with a path and then navigate anywhere my .onAppear for my FIRST tab gets call endlessly. I’ll sometimes see a “double push” to the stack. (Someone posted a video of this happening on Mastodon, which apparently I’m not allowed to link to here.) The second tab is accessing the path property via an @EnvironmentObject.

I can stop this endless loop by removing @Published from the property in my ObservableObject that holds my path.

But then if I go to my third tab, which does NOT use a path, the .onAppear for my FIRST tab again gets called endlessly.

So far on Mastodon I’ve seen three people encountering problems possibly related to storing a path in something being observed.

Feedback requires a sample project, which I am having trouble creating to show the problem.

I was able to recreate the double push part of the problem so I opened feedback.

FB14270042

Some more context:

The first time I encountered this endless loop was in this scenario: App launches and brings up default tab which I call my starting view. I found that when I switched to another tab but then went back to my first tab my .onAppear for the starting view would get called endlessly.

I “fixed” this by switching the .onAppear to .task instead BUT .task ended up being called twice in this same scenario. Still not ideal but better than endless.

I figured out how to make the endless loop stop. So I now have workarounds to both scenarios.

I am able to recreate the "double push" after navigation behavior in a sample project. I am able to stop it by removing @Published from my property that holds a navigation path in my @ObservableObject.

Also, adding @ObservationIgnored to a similar property in an @Observable apparently works also.

I am NOT able to recreate the endless calling of .onAppear/.task in a sample project. I am able to stop it in my app by removing @Published from my property that holds the selected tab in my @ObservableObject.

This is code that is functioning without an issue with iOS 17. I only encountered these problems when building for iOS 18.

My celebration was short lived because I found another situation that triggers the same endless loop behavior.

I have a @Published property that controls what sheet is launched. Populating it causes this same loop. And this time removing @Published makes the sheet logic stop working.

So I don't have a workaround any more.

Infinite loop using NavigationStack
 
 
Q