Navigation: update multiple times per frame

After updating to NavigationStack with nested navigation links (with navigation links in a navigation destination), I see a lot of warnings in Xcode 14 beta:

Update NavigationAuthority bound path tried to update multiple times per frame.

Update NavigationAuthority possible destinations tried to update multiple times per frame.

The app often freezes when navigated with a NavigationLink. Do others see these problems?

Post not yet marked as solved Up vote post of yvsong Down vote post of yvsong
12k views
  • I do have the same issues but haven’t found the solution yet. It seems to be related to FetchRequest. Are you using Core Data in your app?

Add a Comment

Replies

Same problem if I append a value to path (NavigationPath).

In a project using Core Data where I pass multiple objects to the navigationDestination (see example below), I'm seeing a lot of "Update NavigationAuthority possible destinations tried to update multiple times per frame." when I navigate in the Stack. After few push and pop in the stack, the app freezes, the memory increases, the CPU runs at 100%, then the app crashes. I checked the logs from my device: the issues are different every time, but it seems to be linked to a UI update.

.navigationDestination(for: Paragraph.self) { paragraph in
    ParagraphDetail(
        post: post,
        paragraph: paragraph) // -> Update NavigationAuthority possible destinations tried to update multiple times per frame.
}

In a NavigationStack where I only pass one object in the navigationDestination (see below), I don't have this log message, and the app never freezes.

.navigationDestination(for: Paragraph.self) { paragraph in
    ParagraphDetailOnlyParagraph(paragraph: paragraph)
}

To identify if it's related to Core Data or not, I reproduced the same NavigationStack with plain Structs, or simple Class objects. I don't see the log message, even when I pass multiple objects to the navigationDestination. The app never freezes.

I'll file a FB. It seems to be a bug in beta 1.

Same here using NavigationSplitView instead of stack.

I'm seeing similarly on Beta 4, though I didn't seem to see this on the earlier betas. Same scenario as the folks above though with regard to using nested NavigationLinks within a NavigationStack and also Core Data. Seems to be doing what the warning says and calling that destination over and over, until the app freezes.

Same problem if I append a value to path (NavigationPath). Tested in Xcode 14 beta 5

I'm also seeing this or something similar starting with beta 5. I have a NavigationLink/navigationDestination with a NSManagedObject item in one view and another NavigationLink/navigationDestination combo in the destination view using another NSManagedObject item. When the outer NavigationLink is tapped, it just sits there and hangs with 100% CPU and running up memory like crazy. Putting a breakpoint in the upper navigationDestination reveals it getting called over and over so it's probably some kind of recursion in the SwiftUI framework.

If I change the upper NavigationLink to the older-style without an item or navigationDestination modifier, it works. This however reveals another SwiftUI bug that I already wrote a feedback ticket for in an early beta (FB10260549) where mixing the old style NavigationLink at a higher level with the new style links with items at a lower level results in the lower links not working.

So I've been trying to isolate the problem in a simpler sample app to attach to a new feedback ticket but I can't seem to reproduce it in the sample app. It's driving me crazy. I hope someone else has better luck and submits a feedback ticket for this.

  • I was finally able to isolate my hang issue to a simple app for submission of a feedback ticket and it turns out it was not even related to Core Data in my case. In my case, the hang was happening when I had a generic destination view and a generic wrapper struct for the inner NavigationLink item combined with also using an @AppStorage in that generic destination view as well. Oddly enough, either removing the @AppStorage or changing the wrapper struct to use a concrete type fixed it for me!

Add a Comment

I have the same problem.

@State private var path: [Route] = []

NavigationStack(path: $path) {
      Button("Settings") {
          path.append(.settings)
      }
      .navigationDestination(for: Route) { route in
          if route == .setting {
             SettingsView()
          } else {
             EmptyView()
          }
      }
 }

If i use NavigationLink in SettingsView, and there is a @Appstorage variable in it, will lead to an infinite loop.

Can NavigationStack(with NavigationPath binding) and NavigationLink be used together?

The old API not work well.

NavigationLink("About") { AboutView() }

But the new API works.

NavigationLink("About", value: .about)
  • After converting all navigation links to value setting versions, I still see the warnings and poor performance in Xcode 14 RC.

Add a Comment

Got the same issue. I explained it all here.

I have the same issue where appending to the path for a NavigationStack and seeing "Update NavigationRequestObserver tried to update multiple times per frame." I can't reproduce it in a simple app but in my real app I have this message and 100% CPU usage and freezing issues. If I can determine a cause I will update here.

same issue when tapping on NavigaitonLink. using new swiftui syntax but not using the programmatic way. 100% CPU freeze.

add .id(UUID()) on the NavigationLink fixes it for me in some cases. I think it's a bug in swiftUI. and I'm sure that there are more appropriate ways of assigning the id, but if u ensure the id is unique then it will fix the freeze in some cases.

still doesn't fix it for everything.

I'm having the same problem. My app would just freeze on a black screen on launch and would do absolutely nothing until I commented out all the .navigationDestination() calls.

I was able to hack around it by elevating the .navigationDestination() calls closer to the NavigationStack they're in. This obviously isn't ideal and doesn't allow for as easily passing data nested in a view, but it's working for me for now.

Maybe it was just my misunderstanding of the API in the first place and the navigationDestinations aren't supposed to depend on any data in the view presenting them other than what's passed in explicitly in the call. Most of my calls were just passing in the data for the View plus a binding to the NavigationPath, so it wasn't a problem to elevate them.

Hope this helps someone.

Same issue here when I try to include a .navigationDestination() modifier in my view. What I found out is that if we don't pass any variable(including a let, var or those wrapped in @State,@AppStorage,etc or passed through .environmentObject(some variable) ) to the destination view, it's perfectly fine. For example:

.navigationDestination(Int.self){
   Text("Hello World")
}

However if we do so, it will definitely cause an infinite loop, like the code below(where name is a property of our view):

.navigationDestination(Int.self){
   Text("Hello,\(name)")
}

I ran into the same problem and was able to resolve it by replacing the "NavigationLink(value:" with a button instead:

// Used for programmatic navigation
@EnvironmentObject var router: Router


Button {
    router.path.append(SettingsView())
} label: {
    Label("Settings", systemImage: "gearshape")
} 


class Router: ObservableObject {
     @Published var path = [Destination]()

     func goBack() {
         // Navigate back to the previous view
         path.removeLast()
     }
   
     func goToRoot() {
         // Navigate back all the way to the root view
         path = []
     }
}