0

次のシナリオがあります-ReactiveSwiftを使用Actionして、アプリでネットワークリクエストをトリガーしています。このネットワーク リクエストは、そのレスポンスに対して行われる処理のために、コストがかかる可能性があります。したがって、発信者がアクションを適用しようとすると、次のことを行いたいと思います。

  • アクションがすでに進行中かどうかを判断する
    • そうである場合、進行中のアクションの結果を観察する SignalProducer を返します。
    • そうでない場合は、開始時にアクションを適用する SignalProducer を返します。

Action呼び出し元が別のスレッドからを適用しようとする可能性があるため、ソリューションはスレッド セーフであることが理想的です。

これで、ReactiveSwift のキャッシングの例を使用して機能するものをまとめることができましたが、特に完了時にリセットMutablePropertyする必要がある方法で、何か間違ったことをしていることはほぼ確実です。の複数のインスタンスが意図した動作をバイパスできないようにするために、静的変数も使用していることに注意してください。また、私の例では信号出力が表示されますが、実際には次のようになる場合があります。nilActionUseCaseNever

class UseCase {
  private static let sharedAction = Action<Void, Never, AnyError> {
    return SignalProducer.empty.delay(10, on: QueueScheduler.main).on(completed: {
      print("Done")
      UseCase.sharedProducer.value = nil
    })
  }
  private static let sharedProducer = MutableProperty<SignalProducer<Never, AnyError>?>(nil)

  func sync() -> SignalProducer<Never, AnyError> {
    let result = UseCase.sharedProducer.modify { value -> Result<SignalProducer<Never, AnyError>, NoError> in
        if let inProgress = value {
          print("Using in progress")
          return Result(value: inProgress)
        } else {
          print("Starting new")
          let producer = UseCase.sharedAction.apply().flatMapError { error -> SignalProducer<Never, AnyError> in
              switch error {
              case .disabled:                   return SignalProducer.empty
              case .producerFailed(let error):  return SignalProducer(error: error)
              }
            }.replayLazily(upTo: 1)

          value = producer
          return Result(value: producer)
        }
    }

    guard let producer = result.value else {
      fatalError("Unexpectedly found nil producer")
    }

    return producer
  }
}
4

1 に答える 1