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
都试图同时更新状态变量 selected
。 List(selection:)
和 NavigationLink
都可以处理导航任务。解决办法是放弃其中之一。您可以使用其中任何一种来处理导航。
因为 List
看起来不错,我建议坚持下去。然后可以删除 NavigationLink
。 NavigationView
下的第二个视图显示在右边,那为什么不用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"))
}
}
}
}
我在 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
都试图同时更新状态变量 selected
。 List(selection:)
和 NavigationLink
都可以处理导航任务。解决办法是放弃其中之一。您可以使用其中任何一种来处理导航。
因为 List
看起来不错,我建议坚持下去。然后可以删除 NavigationLink
。 NavigationView
下的第二个视图显示在右边,那为什么不用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"))
}
}
}
}