给定一个计时器列表,如果其中一个计时器完成,如何输出,同时还能够重置列表?
Given a list of timers, how to output if one of them completed, while also being able to reset the list?
我有一个输出信号,当给定的一组定时器中的一个超时、完成或整个列表被重置时,它应该输出。
enum DeviceActionStatus {
case pending
case completed
case failed
}
struct DeviceAction {
let start: Date
let status: DeviceActionStatus
func isTimedOut() -> Bool // if start is over 30 seconds ago
let id: String
}
输出信号:
let pendingActionUpdated: Signal<[DeviceAction], NoError>
输入:
let completeAction: Signal<String, NoError>
let tick: Signal<Void, NoError> // runs every 1 second and should iterate to see if any DeviceAction is timed out
let addAction: Signal<DeviceAction, NoError>
let resetAllActions: Signal<Void, NoError>
它应该输出所有 运行ning 设备操作的数组。
let output = Signal.combineLatest(
addAction,
resetAllActions,
tick,
Signal.merge(
completeAction,
tick.take(first: 1).map { _ in "InvalidActionId" }
)) // make sure the combinelatest can fire initially
我尝试将其发送到 .scan 以在每次触发 addAction
时进行累积,并在每次触发 resetAllActions
时重置,但由于无法知道哪个在那些被解雇的人中,我无法使逻辑起作用。我怎样才能既累积不断增长的列表,又能够 运行 通过它并能够在需要时重置它?
在这里看到完整的用例有点困难,所以我将只描述如何区分 addAction
和 resultAllActions
被触发,其余的设计不用管。
您可以在 Signal.combineLatest
之前将这两个合并为一个信号。为此,您需要将它们映射到同一类型。枚举是完美的:
enum Action {
case add(DeviceAction)
case resetAll
}
现在您可以映射每个信号并将它们合并为一个信号:
let action = Signal.merge(
addAction.map { Action.add([=11=]) },
resetAllActions.map { _ in Action.resetAll })
现在您可以打开 scan
中的值并确定它是添加的新操作还是重置。
这看起来像是 merge/enum 模式的工作。我自己更喜欢 RxSwift,但如果你将每个信号映射到一个枚举中并合并它们,那么你就可以将它们正确地接收到你的扫描中......
enum ActionEvent {
case complete(String)
case tick
case add(DeviceAction)
case reset
}
merge(
completeAction.map { ActionEvent.complete([=10=]) },
tick.map { ActionEvent.tick },
addAction.map { ActionEvent.add([=10=]) },
resetAllActions.map { ActionEvent.reset }
).scan([DeviceAction]()) { actions, event in
switch event {
case let .complete(id):
return actions.filter { [=10=].id != id }
case .tick:
return actions.filter { [=10=].isTimedOut() == false }
case let .add(action):
return actions + [action]
case .reset:
let resetDate = Date()
return actions.map { [=10=].start = resetDate }
// or
return []
// depending on what "reset" means.
}
我有一个输出信号,当给定的一组定时器中的一个超时、完成或整个列表被重置时,它应该输出。
enum DeviceActionStatus {
case pending
case completed
case failed
}
struct DeviceAction {
let start: Date
let status: DeviceActionStatus
func isTimedOut() -> Bool // if start is over 30 seconds ago
let id: String
}
输出信号:
let pendingActionUpdated: Signal<[DeviceAction], NoError>
输入:
let completeAction: Signal<String, NoError>
let tick: Signal<Void, NoError> // runs every 1 second and should iterate to see if any DeviceAction is timed out
let addAction: Signal<DeviceAction, NoError>
let resetAllActions: Signal<Void, NoError>
它应该输出所有 运行ning 设备操作的数组。
let output = Signal.combineLatest(
addAction,
resetAllActions,
tick,
Signal.merge(
completeAction,
tick.take(first: 1).map { _ in "InvalidActionId" }
)) // make sure the combinelatest can fire initially
我尝试将其发送到 .scan 以在每次触发 addAction
时进行累积,并在每次触发 resetAllActions
时重置,但由于无法知道哪个在那些被解雇的人中,我无法使逻辑起作用。我怎样才能既累积不断增长的列表,又能够 运行 通过它并能够在需要时重置它?
在这里看到完整的用例有点困难,所以我将只描述如何区分 addAction
和 resultAllActions
被触发,其余的设计不用管。
您可以在 Signal.combineLatest
之前将这两个合并为一个信号。为此,您需要将它们映射到同一类型。枚举是完美的:
enum Action {
case add(DeviceAction)
case resetAll
}
现在您可以映射每个信号并将它们合并为一个信号:
let action = Signal.merge(
addAction.map { Action.add([=11=]) },
resetAllActions.map { _ in Action.resetAll })
现在您可以打开 scan
中的值并确定它是添加的新操作还是重置。
这看起来像是 merge/enum 模式的工作。我自己更喜欢 RxSwift,但如果你将每个信号映射到一个枚举中并合并它们,那么你就可以将它们正确地接收到你的扫描中......
enum ActionEvent {
case complete(String)
case tick
case add(DeviceAction)
case reset
}
merge(
completeAction.map { ActionEvent.complete([=10=]) },
tick.map { ActionEvent.tick },
addAction.map { ActionEvent.add([=10=]) },
resetAllActions.map { ActionEvent.reset }
).scan([DeviceAction]()) { actions, event in
switch event {
case let .complete(id):
return actions.filter { [=10=].id != id }
case .tick:
return actions.filter { [=10=].isTimedOut() == false }
case let .add(action):
return actions + [action]
case .reset:
let resetDate = Date()
return actions.map { [=10=].start = resetDate }
// or
return []
// depending on what "reset" means.
}