RACCommand.h 5.1 KB

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