有没有一种方法可以发出类似于 combineLatest 的信号,而不需要所有信号都在最初触发?

Is there a way to make a signal similar to combineLatest without needing all the signals to initially fire?

我有一组信号

var signals = [Signal<ActionResult?, NoError>]()

其中

enum ActionResult
    case failed
    case pending
    case completed
}

我想创建一个组合信号,如果一个或多个信号触发 .pending

,则 returns 为真
let doesAnyOfTheActionsLoad = Signal.combineLatest(signals).map { values in

     values.reduce(false, { (result, nextResult) -> Bool in
         if result == true { return true }

             if case .pending? = nextResult {
                 return true
             }
         return false
     })
}

我唯一的问题是 combineLatest 仅在所有信号都至少触发一次时才会触发,而且我需要我的信号触发,而不管所有信号是否都触发了。有没有办法在 ReactiveSwift 中做到这一点?

试试这个:

 let doesAnyOfTheActionsLoad = Signal.merge(signals).map { [=10=] == .pending}

如果您希望信号在一个 .pending 之后保持为真,那么您需要使用类似 scan 运算符的东西来存储当前状态:

let doesAnyOfTheActionsLoad = Signal.merge(signals).scan(false) { state, next in
    if case .pending? = next {
        return true
    }
    else {
        return state
    }
}

scan 就像 reduce 的 "live" 响应式版本;每次有新值进入并累积时,它都会发送当前结果。

其他解决方案在技术上是正确的,但我认为这可能更适合您的用例。

// Only ever produces either a single `true` or a single `false`.
let doesAnyOfTheActionsLoad = 
    SignalProducer<Bool, NoError>
        .init(signals)
        .flatten(.merge) // Merge the signals together into a single signal.
        .skipNil() // Discard `nil` values.
        .map { [=10=] == .pending } // Convert every value to a bool representing whether that value is `.pending`.
        .filter { [=10=] } // Filter out `false`.
        .concat(value: false) // If all signals complete without going to `.pending`, send a `false`.
        .take(first: 1) // Only take one value (so we avoid the concatted value in the case that something loads).