You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
3.3 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. //
  2. // repeatWithBehavior.swift
  3. // RxSwiftExt
  4. //
  5. // Created by Marin Todorov on 05/08/2017.
  6. // Copyright © 2016 RxSwift Community. All rights reserved.
  7. //
  8. import Foundation
  9. import RxSwift
  10. public typealias RepeatPredicate = () -> Bool
  11. /*
  12. Uses RepeatBehavior defined in retryWithBehavior
  13. */
  14. /** Dummy error to use with catchError to restart the observable */
  15. private enum RepeatError: Error {
  16. case catchable
  17. }
  18. extension ObservableType {
  19. /**
  20. Repeats the source observable sequence using given behavior when it completes
  21. - parameter behavior: Behavior that will be used when the observable completes
  22. - parameter scheduler: Schedular that will be used for delaying subscription after error
  23. - parameter shouldRepeat: Custom optional closure for decided whether the observable should repeat another round
  24. - returns: Observable sequence that will be automatically repeat when it completes
  25. */
  26. public func repeatWithBehavior(_ behavior: RepeatBehavior, scheduler: SchedulerType = MainScheduler.instance, shouldRepeat: RepeatPredicate? = nil) -> Observable<Element> {
  27. return repeatWithBehavior(1, behavior: behavior, scheduler: scheduler, shouldRepeat: shouldRepeat)
  28. }
  29. /**
  30. Repeats the source observable sequence using given behavior when it completes
  31. - parameter currentRepeat: Number of the current repetition
  32. - parameter behavior: Behavior that will be used in case of completion
  33. - parameter scheduler: Schedular that will be used for delaying subscription after error
  34. - parameter shouldRepeat: Custom optional closure for decided whether the observable should repeat another round
  35. - returns: Observable sequence that will be automatically repeat when it completes
  36. */
  37. internal func repeatWithBehavior(_ currentRepeat: UInt, behavior: RepeatBehavior, scheduler: SchedulerType = MainScheduler.instance, shouldRepeat: RepeatPredicate? = nil)
  38. -> Observable<Element> {
  39. guard currentRepeat > 0 else { return Observable.empty() }
  40. // calculate conditions for bahavior
  41. let conditions = behavior.calculateConditions(currentRepeat)
  42. return concat(Observable.error(RepeatError.catchable))
  43. .catchError {error in
  44. //if observable errors, forward the error
  45. guard error is RepeatError else {
  46. return Observable.error(error)
  47. }
  48. //repeat
  49. guard conditions.maxCount > currentRepeat else { return Observable.empty() }
  50. if let shouldRepeat = shouldRepeat, !shouldRepeat() {
  51. // also return error if predicate says so
  52. return Observable.empty()
  53. }
  54. guard conditions.delay != .never else {
  55. // if there is no delay, simply retry
  56. return self.repeatWithBehavior(currentRepeat + 1, behavior: behavior, scheduler: scheduler, shouldRepeat: shouldRepeat)
  57. }
  58. // otherwise retry after specified delay
  59. return Observable<Void>.just(()).delaySubscription(conditions.delay, scheduler: scheduler).flatMapLatest {
  60. self.repeatWithBehavior(currentRepeat + 1, behavior: behavior, scheduler: scheduler, shouldRepeat: shouldRepeat)
  61. }
  62. }
  63. }
  64. }