我有一个需要在日期变化时重新评估的发布者,但应该在任何其他时间继续发出值。
因此,我认为我可以为UIApplication.significantTimeChangeNotification
通知使用NotificationCenter
发布者,并将其与我的发布者组合在一起,这样组合排放过程将在数据更改或日期更改时重新运行,从而重新评估地图过滤器。请参阅下面代码的大致轮廓。
问题是NotificationCenter
在设置时没有发布事件,因此,以下map
等调用实际上都没有评估。merge(with:)
不能工作,因为两个发布者发布不同的类型,但combineLatest(_:)
和zip(_:)
都不会发出事件,直到两个发布者都发出了一个事件。
我可以通过在这段代码之后添加NotificationCenter.default.post(name: UIApplication.significantTimeChangeNotification, object: nil)
来验证我的代码是否按预期运行,但这是不希望的,因为它可能会向应用程序的其他区域发出信号,当它没有
private func todaysDate() -> String {
let formatter = DateFormatter()
formatter.dateFormat = "YYYY-MM-dd"
return formatter.string(from: Date())
}
@Published var entities: [MyEntity]
let dayChangePublisher = NotificationCenter.default
.publisher(for: UIApplication.significantTimeChangeNotification)
$entities.combineLatest(dayChangePublisher)
.map(.0) // Only pass on the entity for further operations
.map { entities -> MyEntity? in
let today = todaysDate()
return entities?.first(where: { $0.id == today })
}
...remainder of combine code
这种发布者和事件评估的结合可以在当前的Swift组合框架中实现吗?就像我期望的merge(with:)
的行为一样,但是发布者发出两种不同的类型。
编辑:我找到了一个解决方案,我将通知发布者映射到nil数组
let dayChangePublisher = NotificationCenter.default
.publisher(for: UIApplication.significantTimeChangeNotification)
.map { _ ➝ [MyEntity]? in
return nil
}
然后使用merge
和compactMap
来避免在
上传递任何nil值let mergedPub = repo.$entities
.merge(with: dayChangePublisher)
.compactMap { entity -> MyEntity? in
let today = todaysDate()
return entities?.first { $0.id == today }
}
.share()
它可以工作,但如果有人有更好的解决方案可能有点麻烦?
如果我理解了你的问题,你需要一个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 })
}
//...