添加到一对多关系而不更新 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 主体不会被调用。