RACCommand.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. //
  2. // RACCommand.h
  3. // ReactiveObjC
  4. //
  5. // Created by Josh Abernathy on 3/3/12.
  6. // Copyright (c) 2012 GitHub, Inc. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. @class RACSignal<__covariant ValueType>;
  10. NS_ASSUME_NONNULL_BEGIN
  11. /// The domain for errors originating within `RACCommand`.
  12. extern NSString * const RACCommandErrorDomain;
  13. /// -execute: was invoked while the command was disabled.
  14. extern const NSInteger RACCommandErrorNotEnabled;
  15. /// A `userInfo` key for an error, associated with the `RACCommand` that the
  16. /// error originated from.
  17. ///
  18. /// This is included only when the error code is `RACCommandErrorNotEnabled`.
  19. extern NSString * const RACUnderlyingCommandErrorKey;
  20. /// A command is a signal triggered in response to some action, typically
  21. /// UI-related.
  22. @interface RACCommand<__contravariant InputType, __covariant ValueType> : NSObject
  23. /// A signal of the signals returned by successful invocations of -execute:
  24. /// (i.e., while the receiver is `enabled`).
  25. ///
  26. /// Errors will be automatically caught upon the inner signals, and sent upon
  27. /// `errors` instead. If you _want_ to receive inner errors, use -execute: or
  28. /// -[RACSignal materialize].
  29. ///
  30. /// Only executions that begin _after_ subscription will be sent upon this
  31. /// signal. All inner signals will arrive upon the main thread.
  32. @property (nonatomic, strong, readonly) RACSignal<RACSignal<ValueType> *> *executionSignals;
  33. /// A signal of whether this command is currently executing.
  34. ///
  35. /// This will send YES whenever -execute: is invoked and the created signal has
  36. /// not yet terminated. Once all executions have terminated, `executing` will
  37. /// send NO.
  38. ///
  39. /// This signal will send its current value upon subscription, and then all
  40. /// future values on the main thread.
  41. @property (nonatomic, strong, readonly) RACSignal<NSNumber *> *executing;
  42. /// A signal of whether this command is able to execute.
  43. ///
  44. /// This will send NO if:
  45. ///
  46. /// - The command was created with an `enabledSignal`, and NO is sent upon that
  47. /// signal, or
  48. /// - `allowsConcurrentExecution` is NO and the command has started executing.
  49. ///
  50. /// Once the above conditions are no longer met, the signal will send YES.
  51. ///
  52. /// This signal will send its current value upon subscription, and then all
  53. /// future values on the main thread.
  54. @property (nonatomic, strong, readonly) RACSignal<NSNumber *> *enabled;
  55. /// Forwards any errors that occur within signals returned by -execute:.
  56. ///
  57. /// When an error occurs on a signal returned from -execute:, this signal will
  58. /// send the associated NSError value as a `next` event (since an `error` event
  59. /// would terminate the stream).
  60. ///
  61. /// After subscription, this signal will send all future errors on the main
  62. /// thread.
  63. @property (nonatomic, strong, readonly) RACSignal<NSError *> *errors;
  64. /// Whether the command allows multiple executions to proceed concurrently.
  65. ///
  66. /// The default value for this property is NO.
  67. @property (atomic, assign) BOOL allowsConcurrentExecution;
  68. /// Invokes -initWithEnabled:signalBlock: with a nil `enabledSignal`.
  69. - (instancetype)initWithSignalBlock:(RACSignal<ValueType> * (^)(InputType _Nullable input))signalBlock;
  70. /// Initializes a command that is conditionally enabled.
  71. ///
  72. /// This is the designated initializer for this class.
  73. ///
  74. /// enabledSignal - A signal of BOOLs which indicate whether the command should
  75. /// be enabled. `enabled` will be based on the latest value sent
  76. /// from this signal. Before any values are sent, `enabled` will
  77. /// default to YES. This argument may be nil.
  78. /// signalBlock - A block which will map each input value (passed to -execute:)
  79. /// to a signal of work. The returned signal will be multicasted
  80. /// to a replay subject, sent on `executionSignals`, then
  81. /// subscribed to synchronously. Neither the block nor the
  82. /// returned signal may be nil.
  83. - (instancetype)initWithEnabled:(nullable RACSignal<NSNumber *> *)enabledSignal signalBlock:(RACSignal<ValueType> * (^)(InputType _Nullable input))signalBlock;
  84. /// If the receiver is enabled, this method will:
  85. ///
  86. /// 1. Invoke the `signalBlock` given at the time of initialization.
  87. /// 2. Multicast the returned signal to a RACReplaySubject.
  88. /// 3. Send the multicasted signal on `executionSignals`.
  89. /// 4. Subscribe (connect) to the original signal on the main thread.
  90. ///
  91. /// input - The input value to pass to the receiver's `signalBlock`. This may be
  92. /// nil.
  93. ///
  94. /// Returns the multicasted signal, after subscription. If the receiver is not
  95. /// enabled, returns a signal that will send an error with code
  96. /// RACCommandErrorNotEnabled.
  97. - (RACSignal<ValueType> *)execute:(nullable InputType)input;
  98. @end
  99. NS_ASSUME_NONNULL_END