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