Swift 如何使用Combine分配从核心数据获取请求返回的元素数?

Swift 如何使用Combine分配从核心数据获取请求返回的元素数?,swift,core-data,combine,Swift,Core Data,Combine,我希望我的应用程序定期获取新记录并将其存储在核心数据中。我的UI上有一个标签,它应该显示特定记录的元素数量,我希望随着更多记录添加到数据库中,该数量会更新。作为练习,我想用Combine来完成它 当应用程序启动时,我能够显示数据库中元素的数量,但当新数据进入数据库时,该数量不会更新(我通过实现一个手动刷新UI的按钮来验证是否添加了新数据) 以下代码在启动时显示正确的元素数,但在添加新记录时不会更新: let-replayRecordFetchRequest:NSFetchRequest=Repl

我希望我的应用程序定期获取新记录并将其存储在核心数据中。我的UI上有一个标签,它应该显示特定记录的元素数量,我希望随着更多记录添加到数据库中,该数量会更新。作为练习,我想用Combine来完成它

当应用程序启动时,我能够显示数据库中元素的数量,但当新数据进入数据库时,该数量不会更新(我通过实现一个手动刷新UI的按钮来验证是否添加了新数据)

以下代码在启动时显示正确的元素数,但在添加新记录时不会更新:

let-replayRecordFetchRequest:NSFetchRequest=ReplayRecord.fetchRequest()
_试试看?persistentContainer.viewContext.fetch(replayRecordFetchRequest).publisher.count().map{String(格式:Constants.Strings.playsText,$0)}.assign(to:\.text,on:self.playsLabel)
以下是我改编的WWDC 2019会话230演讲中的一段代码片段,但根本不起作用(订户从未被解雇):

let-replayRecordFetchRequest:NSFetchRequest=ReplayRecord.fetchRequest()
如果让replayRecords=try?replayRecordFetchRequest.execute(){
_=replayRecords.publisher.count().map{String(格式:Constants.Strings.playsText,$0)}.assign(to:\.text,on:self.playsLabel)
}

所以,我直到现在才知道这一点,但并不是所有的出版商都是无限活跃的

问题是,
NSFetchRequest.publisher
不是一个长寿的发布者。它只是提供了一种在fetch请求中遍历元素序列的方法。因此,订阅服务器将在元素迭代后取消。在我的例子中,我计算了在取消之前发布的元素,然后将该值分配到UI上

相反,我应该订阅对托管对象上下文的更改,并将该管道分配给我的UI。下面是一些示例代码:

extension NotificationCenter.Publisher{
func上下文(fetchRequest:NSFetchRequest)->publisher.CompactMap{
在中返回compactMap{notification->[T]
让context=notification.object作为!NSManagedObjectContext
var结果:[T]?
context.performAndWait{
结果=try?context.fetch(fetchRequest)
}
返回结果
}
}
}
让playFetchRequest:NSFetchRequest=ReplayRecord.fetchRequest()
让replayVideoFetchRequest:NSFetchRequest=ReplayVideo.fetchRequest()
让playsPublisher=contextDidSavePublisher.context(fetchRequest:playFetchRequest).map(\.count)
让replayVideoPublisher=contextDidSavePublisher.context(fetchRequest:replayVideoFetchRequest.map(\.count)
playsSubscription=playsupblisher.zip(replayVideoPublisher.map){
字符串(格式:Constants.Strings.playsText,$0,$1)
}.receive(on:RunLoop.main)。assign(to:\.text,on:self.playsLabel)

fetch返回一个记录数组,因此您将获得一个数组发布者