首页 > 解决方案 > 如何防止 FetchRequest 观察关系的变化?

问题描述

在我的应用程序中,我有两个 CoreData 实体,它们的关系是一对多的:人物 -> 主题

我正在使用列表呈现人们的名字

struct PeopleListView: View {
    @FetchRequest(
            entity: People.entity(),
            sortDescriptors: [NSSortDescriptor(keyPath: \People.updatedAt, ascending: false)]
        ) var people: FetchedResults<People>
     
    var body: some View {
        NavigationView {
            List {
                ForEach(people) { person in
                    NavigationLink(destination: PersonView(person: person)) {
                        Text(person.name)
                    }
                }
            }
        }
        
    }

然后在 PersonView 上:

struct PersonView: View {
    var person: Person
    
    @Environment(\.managedObjectContext) var context;
    
    var body: some View {
        List {
            Button(action: {
                self.person.subjects.insert(Subject(context: self.context))
            }, label: { Text("Add Subject") })
            ForEach(Array(person.subjects)) { subject in
                Text(subject.name)
            }
        }
        
        
    }
}

一旦我点击“添加主题”按钮,我就会收到以下警告:

[TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window. Table view: <_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView: 0x7f8e0e822800; baseClass = UITableView; frame = (0 0; 414 896); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x600003f0ed30>; layer = <CALayer: 0x60000315a720>; contentOffset: {0, -140}; contentSize: {414, 748}; adjustedContentInset: {140, 0, 34, 0}; dataSource: <_TtGC7SwiftUIP13$7fff2c9c8ad419ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_GOS_19SelectionManagerBoxS2___: 0x7f8e0cc0e070>>

我认为我的问题实际上是,一旦我向一个人添加主题,FetchRequest 就会“收到通知”并PeopleListView在我打开时重新绘制PersonView

我真的很感激这个问题的适当解决方案,我想应该有一种方法可以说不FetchRequest听关系的变化,但我找不到。

虽然我也有其他解决方案,比如代理主题列表,当我回到 PeopleListView 时只“注入它们”,但这听起来很糟糕。

谢谢!

标签: iosswiftcore-dataswiftui

解决方案


如果您仍然需要避免在获取主要实体期间获取关系,则可以使用 customNSFetchRequest结合 SwiftUI的方法FetchRequest

使用 Xcode 12 / iOS 14 测试

struct PeopleListView: View {

    @FetchRequest
    var people: FetchedResults<People>

    init() {
        let request: NSFetchRequest<People> = People.fetchRequest()
        request.sortDescriptors = []
        request.includesSubentities = false             // << here !!

        _people = FetchRequest(fetchRequest: request)
    }

    // ... other code

推荐阅读