| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- import Foundation
- /// Wraps an Action for use by a GUI control (such as `NSControl` or
- /// `UIControl`), with KVO, or with Cocoa Bindings.
- public final class CocoaAction: NSObject {
- /// The selector that a caller should invoke upon a CocoaAction in order to
- /// execute it.
- public static let selector: Selector = #selector(CocoaAction.execute(_:))
-
- /// Whether the action is enabled.
- ///
- /// This property will only change on the main thread, and will generate a
- /// KVO notification for every change.
- public private(set) var enabled: Bool = false
-
- /// Whether the action is executing.
- ///
- /// This property will only change on the main thread, and will generate a
- /// KVO notification for every change.
- public private(set) var executing: Bool = false
-
- private let _execute: AnyObject? -> Void
- private let disposable = CompositeDisposable()
-
- /// Initializes a Cocoa action that will invoke the given Action by
- /// transforming the object given to execute().
- ///
- /// - note: You must cast the passed in object to the control type you need
- /// since there is no way to know where this cocoa action will be
- /// added as a target.
- ///
- /// - parameters:
- /// - action: Executable action.
- /// - inputTransform: Closure that accepts the UI control performing the
- /// action and returns a value (e.g.
- /// `(UISwitch) -> (Bool)` to reflect whether a provided
- /// switch is currently on.
- public init<Input, Output, Error>(_ action: Action<Input, Output, Error>, _ inputTransform: AnyObject? -> Input) {
- _execute = { input in
- let producer = action.apply(inputTransform(input))
- producer.start()
- }
-
- super.init()
-
- disposable += action.enabled.producer
- .observeOn(UIScheduler())
- .startWithNext { [weak self] value in
- self?.willChangeValueForKey("enabled")
- self?.enabled = value
- self?.didChangeValueForKey("enabled")
- }
-
- disposable += action.executing.producer
- .observeOn(UIScheduler())
- .startWithNext { [weak self] value in
- self?.willChangeValueForKey("executing")
- self?.executing = value
- self?.didChangeValueForKey("executing")
- }
- }
-
- /// Initializes a Cocoa action that will invoke the given Action by always
- /// providing the given input.
- ///
- /// - parameters:
- /// - action: Executable action.
- /// - input: A value given as input to the action.
- public convenience init<Input, Output, Error>(_ action: Action<Input, Output, Error>, input: Input) {
- self.init(action, { _ in input })
- }
-
- deinit {
- disposable.dispose()
- }
-
- /// Attempts to execute the underlying action with the given input, subject
- /// to the behavior described by the initializer that was used.
- ///
- /// - parameters:
- /// - input: A value for the action passed during initialization.
- @IBAction public func execute(input: AnyObject?) {
- _execute(input)
- }
-
- public override class func automaticallyNotifiesObserversForKey(key: String) -> Bool {
- return false
- }
- }
- extension Action {
- /// A UI bindable `CocoaAction`.
- ///
- /// - warning: The default behavior force casts the `AnyObject?` input to
- /// match the action's `Input` type. This makes it unsafe for use
- /// when the action is parameterized for something like `Void`
- /// input. In those cases, explicitly assign a value to this
- /// property that transforms the input to suit your needs.
- public var unsafeCocoaAction: CocoaAction {
- return CocoaAction(self) { $0 as! Input }
- }
- }
|