通过 NavigationLink 传递 FetchedResults

Pass FetchedResults through NavigationLink

我有两个 CoreData 对象:

  1. RoadTrip
  2. StatePlate.

每个 RoadTrip 项包含 NSSetStatePlate

屏幕 1 (TripList) 显示所有 RoadTrip 项的列表。屏幕 2 (StateList) 显示了与用户选择的 RoadTrip 关联的所有 StatePlate 项的列表。在屏幕 2 中选择 StatePlate 项目将切换与该项目关联的布尔值。

尽管我可以显示数据并可以切换每个 StatePlate 的 bool 值,但我没有看到屏幕的 UI 立即发生变化。当 StatePlate 的 bool 值被切换时,它应该在屏幕 2 中从一个部分跳到另一个部分。

如何将此 FetchedObject 正确地从屏幕 1 传递到屏幕 2,以便 UI 与数据绑定?

屏幕 1 (TripList)

struct TripList: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(entity: RoadTrip.entity(), sortDescriptors: []) var roadTripItems: FetchedResults<RoadTrip>
    
    var body: some View {
        List {
            ForEach(roadTripItems, id: \.self) { trip in
                NavigationLink(destination: StateList(trip: trip)
                    .environment(\.managedObjectContext, self.managedObjectContext)) {
                        TripRow(roadTrip: trip)
                }
            }
        }
    }

}

屏幕 2 (StateList)

struct StateList: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    var trip: RoadTrip
    
    var plates: [StatePlate] {
        trip.plateArray
    }
    
    var unseenPlates: [StatePlate] {
        trip.plateArray.filter { ![=11=].hasBeenSeen }
    }
    
    var seenPlates: [StatePlate] {
        trip.plateArray.filter { [=11=].hasBeenSeen }
    }

    var body: some View {
        List {
            if !unseenPlates.isEmpty {
                Section(header: Text("Unseen Plates")) {
                    ForEach(unseenPlates, id: \.self) { plate in
                        StateRow(plate: plate)
                    }
                }
            }

            if !seenPlates.isEmpty {
                Section(header: Text("Seen Plates")) {
                    ForEach(seenPlates, id: \.self) { plate in
                        StateRow(plate: plate)
                    }
                }
            }
            
        }
    }
}

StateRow

struct StateRow: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @ObservedObject var plate: StatePlate
    
    var body: some View {
        Button(action: {
            self.plate.hasBeenSeen.toggle()
            try? self.managedObjectContext.save()
        }) {
            HStack {
                Text(String(describing: plate.name!))
                Spacer()
                if plate.hasBeenSeen {
                    Image(systemName: "eye.fill")
                } else {
                    Image(systemName: "")
                }
            }
        }
    }
}

plate 发生变化时,您的 trip 作为对象不会发生变化,因此即使观察到 UI 也不会刷新。

这是一种可能的强制刷新方法。

struct StateList: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @ObservedObject var trip: RoadTrip     // << make observed

    // .. other code

并为更新的 plate/s

添加处理
StateRow(plate: plate)
  .onReceive(plate.objectWillChange) { _ in
      self.trip.objectWillChange.send()
  }