// // RACCommand.h // ReactiveCocoa // // Created by Josh Abernathy on 3/3/12. // Copyright (c) 2012 GitHub, Inc. All rights reserved. // #import @class RACSignal; /// The domain for errors originating within `RACCommand`. extern NSString * const RACCommandErrorDomain; /// -execute: was invoked while the command was disabled. extern const NSInteger RACCommandErrorNotEnabled; /// A `userInfo` key for an error, associated with the `RACCommand` that the /// error originated from. /// /// This is included only when the error code is `RACCommandErrorNotEnabled`. extern NSString * const RACUnderlyingCommandErrorKey; /// A command is a signal triggered in response to some action, typically /// UI-related. @interface RACCommand : NSObject /// A signal of the signals returned by successful invocations of -execute: /// (i.e., while the receiver is `enabled`). /// /// Errors will be automatically caught upon the inner signals, and sent upon /// `errors` instead. If you _want_ to receive inner errors, use -execute: or /// -[RACSignal materialize]. /// /// Only executions that begin _after_ subscription will be sent upon this /// signal. All inner signals will arrive upon the main thread. @property (nonatomic, strong, readonly) RACSignal *executionSignals; /// A signal of whether this command is currently executing. /// /// This will send YES whenever -execute: is invoked and the created signal has /// not yet terminated. Once all executions have terminated, `executing` will /// send NO. /// /// This signal will send its current value upon subscription, and then all /// future values on the main thread. @property (nonatomic, strong, readonly) RACSignal *executing; /// A signal of whether this command is able to execute. /// /// This will send NO if: /// /// - The command was created with an `enabledSignal`, and NO is sent upon that /// signal, or /// - `allowsConcurrentExecution` is NO and the command has started executing. /// /// Once the above conditions are no longer met, the signal will send YES. /// /// This signal will send its current value upon subscription, and then all /// future values on the main thread. @property (nonatomic, strong, readonly) RACSignal *enabled; /// Forwards any errors that occur within signals returned by -execute:. /// /// When an error occurs on a signal returned from -execute:, this signal will /// send the associated NSError value as a `next` event (since an `error` event /// would terminate the stream). /// /// After subscription, this signal will send all future errors on the main /// thread. @property (nonatomic, strong, readonly) RACSignal *errors; /// Whether the command allows multiple executions to proceed concurrently. /// /// The default value for this property is NO. @property (atomic, assign) BOOL allowsConcurrentExecution; /// Invokes -initWithEnabled:signalBlock: with a nil `enabledSignal`. - (id)initWithSignalBlock:(RACSignal * (^)(id input))signalBlock; /// Initializes a command that is conditionally enabled. /// /// This is the designated initializer for this class. /// /// enabledSignal - A signal of BOOLs which indicate whether the command should /// be enabled. `enabled` will be based on the latest value sent /// from this signal. Before any values are sent, `enabled` will /// default to YES. This argument may be nil. /// signalBlock - A block which will map each input value (passed to -execute:) /// to a signal of work. The returned signal will be multicasted /// to a replay subject, sent on `executionSignals`, then /// subscribed to synchronously. Neither the block nor the /// returned signal may be nil. - (id)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal * (^)(id input))signalBlock; /// If the receiver is enabled, this method will: /// /// 1. Invoke the `signalBlock` given at the time of initialization. /// 2. Multicast the returned signal to a RACReplaySubject. /// 3. Send the multicasted signal on `executionSignals`. /// 4. Subscribe (connect) to the original signal on the main thread. /// /// input - The input value to pass to the receiver's `signalBlock`. This may be /// nil. /// /// Returns the multicasted signal, after subscription. If the receiver is not /// enabled, returns a signal that will send an error with code /// RACCommandErrorNotEnabled. - (RACSignal *)execute:(id)input; @end @interface RACCommand (Unavailable) @property (atomic, readonly) BOOL canExecute __attribute__((unavailable("Use the 'enabled' signal instead"))); + (instancetype)command __attribute__((unavailable("Use -initWithSignalBlock: instead"))); + (instancetype)commandWithCanExecuteSignal:(RACSignal *)canExecuteSignal __attribute__((unavailable("Use -initWithEnabled:signalBlock: instead"))); - (id)initWithCanExecuteSignal:(RACSignal *)canExecuteSignal __attribute__((unavailable("Use -initWithEnabled:signalBlock: instead"))); - (RACSignal *)addSignalBlock:(RACSignal * (^)(id value))signalBlock __attribute__((unavailable("Pass the signalBlock to -initWithSignalBlock: instead"))); @end