为什么使用 viewContext 创建一个新的 CloudKit 项目会无限刷新视图?
Why does creating a new CloudKit item with viewContext infinitely refresh views?
我正在使用 CloudKit 中托管的存储数据创建一个应用程序。当我对任何这些列表项执行正常滑动以删除操作时, deleteAlert()
显示(应该显示)。但是,只要显示警报,代码就会不断循环并创建无限数量的空白 Category
值,并将它们添加到列表中。同时,警报不允许您正常点击任何按钮,但如果您在按钮上滑动手指,您会感觉到很多短的触觉反馈脉冲(我怀疑它也在循环创建许多重叠警报)。
import SwiftUI
struct CategoryListView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(entity: Category.entity(), sortDescriptors: [], animation: .default)
private var categories: FetchedResults<Category>
// Passed value
var accountSelection: String
@State private var deletingItem = false
@State private var deleteIndexSet: IndexSet?
@State private var showingAddView = false
var body: some View {
List {
ForEach(categories) { category in
HStack {
Button(action: {
self.showingAddView.toggle()
}) {
Text("\(category.name ?? "")")
}
}
.alert(isPresented: $deletingItem, content: deleteAlert)
}
.onDelete { indexSet in
self.deletingItem = true
self.deleteIndexSet = indexSet
}
}
}
func deleteAlert() -> Alert {
var deletedCategory = Category(context: viewContext) // removing this line causes everything to work properly
try! deletedCategory = categories[deleteIndexSet?.first ?? 0]
return Alert(
title: Text("Delete \(deletedCategory.name ?? "nil")?"),
message: Text("Deleting \(deletedCategory.name ?? "nil") will not remove all entries from that category."), // TODO: make it so that if entry does not have a category, add it to a "miscellaneous" or "other" category
primaryButton: .cancel(),
secondaryButton: .destructive(Text("Delete"), action: {print("")})
)
}
}
视图不断刷新的原因归结为 @FetchRequest
的工作方式(CloudKit 获取项目的数组)。每当 categories
的值发生变化时(如 @State
和 @ObservedObject
等),它所附加的视图就会刷新。在这种情况下,以下循环将无限重复:
在 deleteAlert()
内部,var deletedCategory = Category(context: viewContext)
创建一个新的 Category
并立即将其添加到当前上下文(列表)。
这会导致视图如前所述进行刷新。
$deletingItem
的值仍然为真,因此将显示另一个警报。
显示警报时,会触发 deleteAlert()
.
中的代码
冲洗并无限次重复步骤 1-4。
TL;DR 不要在 View
/Body
中创建 ManagedObjects
/ObservableObjects
(正如@lorem ipsum 也指出的那样)。
我正在使用 CloudKit 中托管的存储数据创建一个应用程序。当我对任何这些列表项执行正常滑动以删除操作时, deleteAlert()
显示(应该显示)。但是,只要显示警报,代码就会不断循环并创建无限数量的空白 Category
值,并将它们添加到列表中。同时,警报不允许您正常点击任何按钮,但如果您在按钮上滑动手指,您会感觉到很多短的触觉反馈脉冲(我怀疑它也在循环创建许多重叠警报)。
import SwiftUI
struct CategoryListView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(entity: Category.entity(), sortDescriptors: [], animation: .default)
private var categories: FetchedResults<Category>
// Passed value
var accountSelection: String
@State private var deletingItem = false
@State private var deleteIndexSet: IndexSet?
@State private var showingAddView = false
var body: some View {
List {
ForEach(categories) { category in
HStack {
Button(action: {
self.showingAddView.toggle()
}) {
Text("\(category.name ?? "")")
}
}
.alert(isPresented: $deletingItem, content: deleteAlert)
}
.onDelete { indexSet in
self.deletingItem = true
self.deleteIndexSet = indexSet
}
}
}
func deleteAlert() -> Alert {
var deletedCategory = Category(context: viewContext) // removing this line causes everything to work properly
try! deletedCategory = categories[deleteIndexSet?.first ?? 0]
return Alert(
title: Text("Delete \(deletedCategory.name ?? "nil")?"),
message: Text("Deleting \(deletedCategory.name ?? "nil") will not remove all entries from that category."), // TODO: make it so that if entry does not have a category, add it to a "miscellaneous" or "other" category
primaryButton: .cancel(),
secondaryButton: .destructive(Text("Delete"), action: {print("")})
)
}
}
视图不断刷新的原因归结为 @FetchRequest
的工作方式(CloudKit 获取项目的数组)。每当 categories
的值发生变化时(如 @State
和 @ObservedObject
等),它所附加的视图就会刷新。在这种情况下,以下循环将无限重复:
在
deleteAlert()
内部,var deletedCategory = Category(context: viewContext)
创建一个新的Category
并立即将其添加到当前上下文(列表)。这会导致视图如前所述进行刷新。
$deletingItem
的值仍然为真,因此将显示另一个警报。显示警报时,会触发
中的代码deleteAlert()
.冲洗并无限次重复步骤 1-4。
TL;DR 不要在 View
/Body
中创建 ManagedObjects
/ObservableObjects
(正如@lorem ipsum 也指出的那样)。