Core data 当用户更改全局对象时重新初始化联合发布服务器

Core data 当用户更改全局对象时重新初始化联合发布服务器,core-data,swiftui,combine,Core Data,Swiftui,Combine,我有一个核心数据发布者,到目前为止工作得很好。我有一个工作区实体和一个项目实体。我使用以下发布服务器获取给定工作区的所有项目: class ProjectModel: ObservableObject { @Published var projects = [Project]() private var cancellableSet: Set<AnyCancellable> = [] init(){ CoreDataPublisher(request: Proj

我有一个核心数据发布者,到目前为止工作得很好。我有一个
工作区
实体和一个
项目
实体。我使用以下发布服务器获取给定工作区的所有项目:

class ProjectModel: ObservableObject {
  @Published var projects = [Project]()
  private var cancellableSet: Set<AnyCancellable> = []

  init(){
    CoreDataPublisher(request: Project.getAllProjects(), context: PersistenceController.shared.container.viewContext)
      .sink(
        receiveCompletion: { print($0) },
        receiveValue: { [weak self] items in
          self?.projects = items
        })
      .store(in: &cancellableSet)
  }
}
工作区
对象处于全局状态类中:

class AppState: ObservableObject{
  static let shared = AppState()
  @Published var workspace: Workspace!

  init(){
    //Setup the workspace for the first time
  }
}
我可以成功地从发布者处接收数据,并且可以成功地更改UI中的全局
工作区。问题是,在更改
工作区
后,发布者仍然指向创建获取请求时最初设置的旧
工作区


AppState
工作区更改时,如何提示
ProjectModel
重新初始化以更新发布者的状态?

在您的
ProjectModel
中,我将从
anycancelable
集合切换到一个特定的集合,以便您可以取消它:

var cdPublisherCancellable : AnyCancellable?
我将此发布服务器的设置移出init,因为您需要再次调用它:

func setupPublisher() {
  cdPublisherCancellable?.cancel()
  cdPublisherCancellable = CoreDataPublisher(request:)...
}
然后,因为workspace是共享AppState上的已发布属性,所以我设置了另一个发布者链接来查看它:

var workspaceCancellable : AnyCancellable?
init() {
  workspaceCancellable = AppState.shared.$workspace.sink { workspace in
    setupPublisher()
  }
}

通常,实现这一点的方法是在发布服务器上使用
flatMap
操作符
flatMap
允许您“根据收到的值创建一个新的发布者,然后将该发布者的输出用作整个发布者链的输出”

它看起来像这样:

AppState.shared.$workspace.flatMap{workspace in
let request=NSFetchRequest(entityName:“\(Project.self)”)
request.sortDescriptors=[NSSortDescriptor(keyPath:\Project.name,升序:true)]
request.predicate=NSPredicate(格式:“workspace=%@”,workspace)
返回CoreDataPublisher(请求:请求,上下文:PersistenceController.shared.container.viewContext)
}
这将为您提供一个新的发布者:

  • 当应用程序状态的
    .workspace
    属性更改时,根据新的
    workspace
    值构造一个新的
    CoreDataPublisher
  • 使用该
    CoreDataPublisher
    作为整个发布服务器流的值源

这真的很有帮助,谢谢。这与Dave的答案基本相同(据我所知)。顺便问一下,您确定在下一行覆盖相同的可取消内容之前必须调用
cdPublisherCancellable?.cancel()
?这难道不能有效地取代它吗?我认为你是对的,出版商应该取消他们自己的Denit——我已经做好了充分的准备,对这类事情要谨慎(特别是在测试期间)
var workspaceCancellable : AnyCancellable?
init() {
  workspaceCancellable = AppState.shared.$workspace.sink { workspace in
    setupPublisher()
  }
}