SwiftUI macOS NavigationView - onChange(of: Bool) 操作尝试每帧更新多次

SwiftUI macOS NavigationView - onChange(of: Bool) action tried to update multiple times per frame

我在 SwiftUI macOS 应用程序侧边栏中单击 NavigationLink 时看到 onChange(of: Bool) action tried to update multiple times per frame 警告。

这是我目前拥有的:

import SwiftUI

@main
struct BazbarApp: App {

    @StateObject private var modelData = ModelData()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(modelData)
        }
    }
}


class ModelData: ObservableObject {
    @Published var myLinks = [URL(string: "https://google.com")!, URL(string: "https://apple.com")!, URL(string: "https://amazon.com")!]
}

struct ContentView: View {

    @EnvironmentObject var modelData: ModelData

    @State private var selected: URL?

    var body: some View {
        NavigationView {

            List(selection: $selected) {
                Section(header: Text("Bookmarks")) {

                    ForEach(modelData.myLinks, id: \.self) { url in
                        NavigationLink(destination: DetailView(selected: $selected) ) {
                            Text(url.absoluteString)
                        }
                        .tag(url)
                    }

                }
            }
            .onDeleteCommand {
                if let selected = selected {
                    modelData.myLinks.remove(at: modelData.myLinks.firstIndex(of: selected)!)
                }

                selected = nil
            }

            Text("Choose a link")
        }
    }
}

struct DetailView: View {
    @Binding var selected: URL?

    var body: some View {

        if let selected = selected {
            Text("Currently selected: \(selected)")
        }
        else {
            Text("Choose a link")
        }
    }
}

当我交替单击边栏中的第二个和第三个 link 时,我最终开始在我的控制台中看到上述警告。

这是我所指内容的动图:

有趣的是,在第一次和第二次之间交替点击时不会出现警告 link。

有人知道如何解决这个问题吗?

我正在使用 macOS 12.2.1 & Xcode 13.2.1.

提前致谢

我认为问题在于 List(selection:)NavigationLink 都试图同时更新状态变量 selectedList(selection:)NavigationLink 都可以处理导航任务。解决办法是放弃其中之一。您可以使用其中任何一种来处理导航。

因为 List 看起来不错,我建议坚持下去。然后可以删除 NavigationLinkNavigationView下的第二个视图显示在右边,那为什么不用DetailView(selected:)呢。您已经将 selected 参数设为绑定变量,因此如果该变量发生变化,视图将更新。

struct ContentView: View {
    
    @EnvironmentObject var modelData: ModelData
    
    @State private var selected: URL?
    
    var body: some View {
        NavigationView {
            
            List(selection: $selected) {
                Section(header: Text("Bookmarks")) {
                    
                    ForEach(modelData.myLinks, id: \.self) { url in
                        Text(url.absoluteString)
                            .tag(url)
                    }
                    
                }
            }
            .onDeleteCommand {
                if let selected = selected {
                    modelData.myLinks.remove(at: modelData.myLinks.firstIndex(of: selected)!)
                }
                
                selected = nil
            }
            
            DetailView(selected: $selected)
        }
    }
}

我可以用我能想到的最简单的例子重现这个问题,所以我猜这是 NavigationView 的一个内部错误。

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink("A", destination: Text("A"))
                NavigationLink("B", destination: Text("B"))
                NavigationLink("C", destination: Text("C"))
            }
        }
    }
}