首页 > 解决方案 > 当用户更改全局对象时重新初始化合并发布者

问题描述

到目前为止,我有一个运行良好的 Core Data 发布者。我有一个Workspace实体和一个Project实体。我使用以下发布者来获取给定工作区的所有项目:

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)
  }
}

获取请求getAllProjects()位于此处的核心数据实体扩展中,其中NSPredicate过滤器基于WorkspaceUI 中设置的对象。

//Core Data Entity Extension
extension Project{
  @nonobjc public class func getAllProjects() -> NSFetchRequest<Project> {
    let workspace = AppState.shared.workspace as Workspace //<-- The user can change this workspace
  
    let request = NSFetchRequest<Project>(entityName: "\(Self.self)")
    request.sortDescriptors = [NSSortDescriptor(keyPath: \Project.name, ascending: true)]
    request.predicate = NSPredicate(format: "workspace = %@", workspace)
    return request
  }
}

这个Workspace对象在一个全局状态类中:

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

  init(){
    //Setup the workspace for the first time
  }
}

我可以成功地从我的发布者那里接收数据,并且可以成功地更改WorkspaceUI 中的全局。问题是在更改 之后Workspace,发布者仍然指向Workspace创建获取请求时最初设置的旧。

当's更改时,如何提示ProjectModel重新初始化以更新发布者的状态?AppStateworkspace

标签: core-dataswiftuicombine

解决方案


通常,实现此目的的方法是使用flatMap发布者上的运算符。flatMap让您“根据收到的值创建一个新的发布者,然后将该发布者的输出用作整个发布者链的输出”。

它看起来像这样:

AppState.shared.$workspace.flatMap { workspace in
    let request = NSFetchRequest<Project>(entityName: "\(Project.self)")
    request.sortDescriptors = [NSSortDescriptor(keyPath: \Project.name, ascending: true)]
    request.predicate = NSPredicate(format: "workspace = %@", workspace)
    return CoreDataPublisher(request: request, context: PersistenceController.shared.container.viewContext)
}

这为您提供了一个新的发布者:

  • 当您的应用程序状态的属性发生变化时,无论新值是什么.workspace,都会构造一个新的CoreDataPublisherWorkspace
  • 将其CoreDataPublisher用作整个发布者流的值的来源

推荐阅读