添加到一对多关系而不更新 UI
Adding to a one-to-many relationship not updating UI
我在 plan -> recipe 的核心数据中有一个一对多的关系。 plan.recipes 属于 NSSet? 类型,因此我创建了具有计算属性的自定义 NSManagedObject 类 以将这些属性转换为数组, 添加一个额外的 属性 recipesArray:
public var recipesArray: [Recipe] {
let set = recipes as? Set<Recipe> ?? []
return set.sorted {
[=11=].wrappedName < .wrappedName
}
}
然后我使用 ForEach 在视图中显示此列表,使用 recipesArray 属性。此视图的子视图调用 plan.addToRecipes(recipe: Recipe),以将新对象添加到关系中。然后我保存。
问题是,父视图中的 ForEach 对此添加没有反应。如果我通过导航离开刷新视图,则会显示新配方,但添加新配方时不会自动更新视图。
有人知道怎么做吗?我应该使用原始的 recipes 属性 而不是这个自定义数组吗?
您需要使用等于给定 plan
的谓词为 Recipe
创建另一个 FetchRequest
,例如像这样:
struct RecipesView: View {
var fetchRequest: FetchRequest<Recipe>
var recipes: FetchedResults<Recipe> { fetchRequest.wrappedValue }
init(plan: Plan) {
let sortDescriptors = ...
let predicate = NSPredicate(format: "plan = %@", plan)
fetchRequest = FetchRequest(sortDescriptors: sortDescriptors, predicate: predicate, animation: .default)
}
var body: some View {
ForEach(recipes) { recipe in
RecipeView(recipe: recipe) // it's important to not access recipe's properties (firing a fault) until inside a sub-view's body.
}
}
}
注意:目前 FetchRequest
中存在一个错误,即使此 View
是具有相同 plan
且因此相同 FetchRequest
的初始化,它也会导致 body 始终被调用.这是因为 FetchRequest
结构每次都会在其中初始化一个新对象,从而导致它以及此视图看起来已更改为 SwiftUI。我 reported this bug 所以希望他们能修复它。同时,您可以使用包装器 View
解决它,该包装器将 plan
作为 let 主体不会被调用。
我在 plan -> recipe 的核心数据中有一个一对多的关系。 plan.recipes 属于 NSSet? 类型,因此我创建了具有计算属性的自定义 NSManagedObject 类 以将这些属性转换为数组, 添加一个额外的 属性 recipesArray:
public var recipesArray: [Recipe] {
let set = recipes as? Set<Recipe> ?? []
return set.sorted {
[=11=].wrappedName < .wrappedName
}
}
然后我使用 ForEach 在视图中显示此列表,使用 recipesArray 属性。此视图的子视图调用 plan.addToRecipes(recipe: Recipe),以将新对象添加到关系中。然后我保存。
问题是,父视图中的 ForEach 对此添加没有反应。如果我通过导航离开刷新视图,则会显示新配方,但添加新配方时不会自动更新视图。
有人知道怎么做吗?我应该使用原始的 recipes 属性 而不是这个自定义数组吗?
您需要使用等于给定 plan
的谓词为 Recipe
创建另一个 FetchRequest
,例如像这样:
struct RecipesView: View {
var fetchRequest: FetchRequest<Recipe>
var recipes: FetchedResults<Recipe> { fetchRequest.wrappedValue }
init(plan: Plan) {
let sortDescriptors = ...
let predicate = NSPredicate(format: "plan = %@", plan)
fetchRequest = FetchRequest(sortDescriptors: sortDescriptors, predicate: predicate, animation: .default)
}
var body: some View {
ForEach(recipes) { recipe in
RecipeView(recipe: recipe) // it's important to not access recipe's properties (firing a fault) until inside a sub-view's body.
}
}
}
注意:目前 FetchRequest
中存在一个错误,即使此 View
是具有相同 plan
且因此相同 FetchRequest
的初始化,它也会导致 body 始终被调用.这是因为 FetchRequest
结构每次都会在其中初始化一个新对象,从而导致它以及此视图看起来已更改为 SwiftUI。我 reported this bug 所以希望他们能修复它。同时,您可以使用包装器 View
解决它,该包装器将 plan
作为 let 主体不会被调用。