首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >给定一个定时器列表,如果其中一个完成了,如何输出,同时也能够重置列表?

问给定一个定时器列表,如果其中一个完成了,如何输出,同时也能够重置列表?
EN

Stack Overflow用户
提问于 2018-11-05 14:05:14
回答 2查看 80关注 0票数 3

我有一个输出信号,当一个给定的计时器集中的一个超时、完成或整个列表被重置时,它应该输出。

代码语言:javascript
复制
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

}

输出信号:

代码语言:javascript
复制
let pendingActionUpdated: Signal<[DeviceAction], NoError>

投入:

代码语言:javascript
复制
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>

它应该输出所有正在运行的设备操作的数组。

代码语言:javascript
复制
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被触发时重置,但是由于无法知道哪些被触发,所以我无法让逻辑工作起来。我如何既能累积一个不断增长的列表,同时又能够在我想要的时候重新设置它?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-05 14:29:32

这看起来像是合并/枚举模式的作业。我自己更像一个RxSwift的家伙,但是如果你把每个信号映射到一个enum中,并将它们合并,那么你就可以将它们正确地接收到扫描中.

代码语言:javascript
复制
enum ActionEvent {
    case complete(String)
    case tick
    case add(DeviceAction)
    case reset
}

merge(
    completeAction.map { ActionEvent.complete($0) },
    tick.map { ActionEvent.tick },
    addAction.map { ActionEvent.add($0) },
    resetAllActions.map { ActionEvent.reset }
).scan([DeviceAction]()) { actions, event in 
    switch event {
    case let .complete(id):
        return actions.filter { $0.id != id }
    case .tick:
        return actions.filter { $0.isTimedOut() == false }
    case let .add(action):
        return actions + [action]
    case .reset:
        let resetDate = Date()
        return actions.map { $0.start = resetDate }
        // or
        return []
        // depending on what "reset" means.
}
票数 2
EN

Stack Overflow用户

发布于 2018-11-05 14:27:30

在这里很难看到完整的用例,所以我将描述如何区分被触发的addAction和resultAllActions,而只剩下剩下的设计。

您可以在Signal.combineLatest之前将这两个信号合并成一个信号。为了做到这一点,需要将它们映射到相同的类型。对于这一点来说,枚举是完美的:

代码语言:javascript
复制
enum Action {
    case add(DeviceAction)
    case resetAll
}

现在,您可以映射每个信号并将它们合并为单个信号:

代码语言:javascript
复制
let action = Signal.merge(
    addAction.map { Action.add($0) },
    resetAllActions.map { _ in Action.resetAll })

现在,您可以打开scan中的值,并确定它是正在添加的新操作还是重置操作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53155980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档