我有一个发布者,需要在日期变化时重新评估,但应该在任何其他时间继续发出值。
\n因此,我认为我可以使用NotificationCenter发布者来UIApplication.significantTimeChangeNotification发送通知,并将其与我的发布者组合起来,以便组合发射过程可以在数据更改或日期更改时重新运行,从而重新评估地图过滤器。请参阅下面该代码的粗略轮廓。
NotificationCenter问题是,在设置时没有发布事件,因此,以下map等调用都不会实际评估。merge(with:)不会起作用,因为两个出版商发布不同的类型,但是combineLatest(_:)和zip(_:)两个发布者都发出单个事件之前,两者都不会发出事件。
我可以通过添加来验证我的代码是否按预期运行NotificationCenter.default.post(name: UIApplication.significantTimeChangeNotification, object: nil),但这是不可取的,因为它可能会向应用程序的其他区域发出信号,表明实际时间更改已发生,而实际上时间更改尚未发生
private func todaysDate() -> String {\n let formatter = DateFormatter()\n formatter.dateFormat = "YYYY-MM-dd"\n return formatter.string(from: Date())\n}\n\n@Published var entities: [MyEntity]\n\nlet dayChangePublisher = NotificationCenter.default\n .publisher(for: UIApplication.significantTimeChangeNotification)\n\n$entities.combineLatest(dayChangePublisher)\n .map(\\.0) // Only pass on the entity for further operations\n .map { entities -> MyEntity? in\n let today = todaysDate()\n return entities?.first(where: { $0.id == today })\n }\n ...remainder of combine code\n\nRun Code Online (Sandbox Code Playgroud)\n当前的 Swift 组合框架可以实现发布者和事件评估的结合吗?就像我期望的行为一样merge(with:),但发布者发出两种不同的类型。
编辑:\n我找到了一种解决方案,将通知发布者映射到 nil 数组
\nlet dayChangePublisher = NotificationCenter.default\n .publisher(for: UIApplication.significantTimeChangeNotification)\n .map { _ \xe2\x9e\x9d [MyEntity]? in\n return nil\n }\nRun Code Online (Sandbox Code Playgroud)\n然后使用merge和compactMap来避免传递任何 nil 值
let mergedPub = repo.$entities\n .merge(with: dayChangePublisher)\n .compactMap { entity -> MyEntity? in\n let today = todaysDate()\n return entities?.first { $0.id == today }\n }\n .share()\nRun Code Online (Sandbox Code Playgroud)\n它有效,但如果有人有更好的解决方案,可能有点麻烦?
\n如果我理解你的问题,你需要一个combineLatest不会因为没有来自发布者之一的初始值而被阻止的。
您可以通过.prepend(value)操作员来实现这一点。在这种情况下,由于您不关心实际值,因此首先映射到Void,然后在前面添加Void. 它会像这样工作:
let dayChangePublisher = NotificationCenter.default
.publisher(for: UIApplication.significantTimeChangeNotification)
$entities.combineLatest(
dayChangePublisher
.map { _ in }
.prepend(()) // make sure to prepend a () value
)
.map(\.0) // Only pass on the entity for further operations
.map { entities -> MyEntity? in
let today = todaysDate()
return entities?.first(where: { $0.id == today })
}
//...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2207 次 |
| 最近记录: |