NavigationLink 在@ObservedObject 改变和使用@AppStorage 时跳回
NavigationLink jumps back when @ObservedObject is changed and @AppStorage is used
我在我的代码中找到了一个烦人的错误,并设法使用 xCode 的默认 iOS 应用程序作为起点并添加了一些代码来重现该问题。
问题
当满足以下条件时,修改@ObservedObject(核心数据实体)的一部分会导致视图立即跳回:
- 视图至少有 2 link 秒深度
- @AppStorage 在另一个视图中声明
我已经确认 (1) 如果我跳过 SubView2 并 link 直接进入 SubView3(编辑视图),那么该行为不会发生,并且 (2) 如果我注释掉 @AppStorage 中的行SettingsView() 则该行为不会发生。
在 SubView3 中,我点击“增加”以增加 item.value + 1。这导致视图跳回到 SubView2。
代码
我使用 CloudKit 和 SwiftUI 启动了一个默认 Xcode 项目,然后添加了一个 SettingsView(其中包含 @AppStorage)和两个子视图来查看特定项目。
import SwiftUI
import CoreData
struct SettingsView: View {
@AppStorage("userSettingOne") var userSettingOne = false
var body: some View {
Text("Hello")
}
}
struct SubView2: View {
@ObservedObject var item2: Item
@State private var showSubView3 = false
var body: some View {
NavigationLink(destination: SubView3(item3: item2) , isActive: $showSubView3) { EmptyView() }
Text("Value: \(item2.value)")
Button("SubView3", action: {
showSubView3 = true
})
.navigationTitle("SubView2")
}
}
struct SubView3: View {
@ObservedObject var item3: Item
var body: some View {
VStack {
Text("Value: \(item3.value)")
Button("Increase", action: {
item3.value += 1
})
}
.navigationTitle("SubView3")
}
}
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
animation: .default)
private var items: FetchedResults<Item>
var body: some View {
NavigationView {
List {
ForEach(items) { item in
NavigationLink("Item", destination: SubView2(item2: item))
}
.onDelete(perform: deleteItems)
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem {
HStack {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
NavigationLink(destination: SettingsView(), label: {
Label("", systemImage: "gear").labelStyle(.iconOnly)
})
}
}
}
Text("Select an item")
}
}
// Boilerplate/default code below here
private func addItem() {
withAnimation {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { items[[=10=]] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
尝试将 .navigationViewStyle(.stack)
添加到您的 NavigationView
我在我的代码中找到了一个烦人的错误,并设法使用 xCode 的默认 iOS 应用程序作为起点并添加了一些代码来重现该问题。
问题
当满足以下条件时,修改@ObservedObject(核心数据实体)的一部分会导致视图立即跳回:
- 视图至少有 2 link 秒深度
- @AppStorage 在另一个视图中声明
我已经确认 (1) 如果我跳过 SubView2 并 link 直接进入 SubView3(编辑视图),那么该行为不会发生,并且 (2) 如果我注释掉 @AppStorage 中的行SettingsView() 则该行为不会发生。
在 SubView3 中,我点击“增加”以增加 item.value + 1。这导致视图跳回到 SubView2。
代码
我使用 CloudKit 和 SwiftUI 启动了一个默认 Xcode 项目,然后添加了一个 SettingsView(其中包含 @AppStorage)和两个子视图来查看特定项目。
import SwiftUI
import CoreData
struct SettingsView: View {
@AppStorage("userSettingOne") var userSettingOne = false
var body: some View {
Text("Hello")
}
}
struct SubView2: View {
@ObservedObject var item2: Item
@State private var showSubView3 = false
var body: some View {
NavigationLink(destination: SubView3(item3: item2) , isActive: $showSubView3) { EmptyView() }
Text("Value: \(item2.value)")
Button("SubView3", action: {
showSubView3 = true
})
.navigationTitle("SubView2")
}
}
struct SubView3: View {
@ObservedObject var item3: Item
var body: some View {
VStack {
Text("Value: \(item3.value)")
Button("Increase", action: {
item3.value += 1
})
}
.navigationTitle("SubView3")
}
}
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
animation: .default)
private var items: FetchedResults<Item>
var body: some View {
NavigationView {
List {
ForEach(items) { item in
NavigationLink("Item", destination: SubView2(item2: item))
}
.onDelete(perform: deleteItems)
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem {
HStack {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
NavigationLink(destination: SettingsView(), label: {
Label("", systemImage: "gear").labelStyle(.iconOnly)
})
}
}
}
Text("Select an item")
}
}
// Boilerplate/default code below here
private func addItem() {
withAnimation {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { items[[=10=]] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
尝试将 .navigationViewStyle(.stack)
添加到您的 NavigationView