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?

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?

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 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)

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 = []
     }
}


I am also seeing the same message. In a mirror situation (almost identical code in a Row/Detail situation where rows navigate to editor details), everything works fine. But in the second situation, I get the message "Update NavigationRequestObserver tried to update multiple times per frame" and 100% CPU hang. I've ripped out everything, so there's barely anything going on, and the problem persists. The differentiator between hangs/doesn't hang seems to be whether a closure in the editor (and one that has not even been invoked) captures a state variable in that editor (View). This makes no sense to me. There must be some strange stuff going on behind the scenes.

I have tried Button vs Navigationlink, to no avail. For now, I also have to conclude this is a swift or swiftUI bug.

FWIW, I am using a NavigationStack with a NavigationPath to control it. I'm always using .navigationDestination to set up the hierarchy. Xcode Version 14.2 (14C18)

I was able to remove the runtime warning using a button instead of a navigation link, similar to RandoCorleones' suggestion. I toggled an isPresented State variable within the button that triggered a navigationDestination.

.navigationDestination(isPresented: $isPresented, destination: {
                TriggeredView()
            })

Maybe this helps anyone:

I was running into this issue and at least found one thing in my code causing this.

I had ViewModels that were handed over to the detail view called by NavigationLink(value:) In the Detail View those ViewModel were

@ObservedObject var someViewModel : SomeViewModel

thus making SwiftUI rerender and recreate that ViewModel in an infinite loop

changing that to a StateObject:

@StateObject var someViewModel : SomeViewModel

helped (in that special case)

I encountered this problem with my NavigationStack when using both NavigationLink with values and without. The navigationStack had to be all NavigationLinks with values or without, I could not mix the two.

NavigationLink(destination: ItemDetail(item: equipItem)) {
                       Text("\(equipItem.name)")
                    }

NavigationLink with no value

NavigationLink(equipItem.name, value: equipItem)
                        .navigationTitle(categoryName)

//
code ....
//

.navigationDestination(for: equipment.self, destination: { equipItem in
                    ItemDetail(item: equipItem)

NavigationLink with a value

According to Google Bard 🤖 this can happen if you are using an ObservableObject @Published property as the path: Binding on a NavigationStack and you are changing the value of the property in the same frame.

⚠️ Something like this triggered the runtime warning for me, despite everything still working properly:

// ViewModel
class MyModelObject: ObservableObject {
    @Published var path: [MyObject] = []
    ...
}


// View
@StateObject var model = MyModelObject()

var body: some View {
    NavigationView(path: $model.path) {
    ...

✅ In the end, the following fixed the runtime warning, I had to make path: read from a @State property Binding and still communicate to the view model using the onChange function.

// ViewModel
class MyModelObject: ObservableObject {
    @Published var path: [MyObject] = []

    ...

    // Useful for manipulating a property observed by other components.
    func update(_ path: [MyObject]) {
        self.path = path
    }
}

// View
@State var presentedPath: [MyObject] = []
@StateObject var model = MyModelObject()

var body: some View {
    NavigationView(path: $presentedPath) {
        ...
    }.onChange(of: presentedPath) { newPath in
        model.update(path: newPath)
    }
}

Hi all. There no solution yet?

@2Jumper3 I was experiencing this issue before even adding any destinations to my NavigationPath.

Switching from NavigationPath to add my routes to an array of Routes resolved my issue. Hope this helps.

From:

var path = NavigationPath()

To:

var path: [Route] = [Route]()
Navigation: update multiple times per frame
 
 
Q