Skip to content

Commit 0f93f52

Browse files
authored
Merge pull request #126 from mosamer/master
Improve naming of public API properties
2 parents 9c413d3 + 72e9ab0 commit 0f93f52

File tree

9 files changed

+52
-33
lines changed

9 files changed

+52
-33
lines changed

Diff for: Changelog.md

+12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ Current master
66

77
- Nothing yet!
88

9+
4.0 (In development)
10+
--------------------
11+
12+
- Cleanup public API [#120](https://github.com/RxSwiftCommunity/Action/issues/120)
13+
- Remove unneccessary properties
14+
- `workFactory`
15+
- `_enabledIf`
16+
- Rename properties to match Swift API design [guidelines](https://swift.org/documentation/api-design-guidelines/#strive-for-fluent-usage)
17+
- `enabled` ~> `isEnabled`
18+
- `executing` ~> `isExecuting`
19+
- Deprecate renamed properties
20+
921
3.5.0
1022
-----
1123

Diff for: Demo/ViewController.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ class ViewController: UIViewController {
6565
// Demo: observe the output of both actions, spin an activity indicator
6666
// while performing the work
6767
Observable.combineLatest(
68-
button.rx.action!.executing,
69-
self.navigationItem.rightBarButtonItem!.rx.action!.executing) { a,b in
68+
button.rx.action!.isExecuting,
69+
self.navigationItem.rightBarButtonItem!.rx.action!.isExecuting) { a,b in
7070
// we combine two boolean observable and output one boolean
7171
return a || b
7272
}
@@ -90,7 +90,7 @@ class ViewController: UIViewController {
9090
}
9191
self.navigationItem.leftBarButtonItem?.rx.bind(to: sharedAction, input: .barButton)
9292

93-
sharedAction.executing.debounce(0, scheduler: MainScheduler.instance).subscribe(onNext: { [weak self] executing in
93+
sharedAction.isExecuting.debounce(0, scheduler: MainScheduler.instance).subscribe(onNext: { [weak self] executing in
9494
if (executing) {
9595
self?.activityIndicator.startAnimating()
9696
}

Diff for: Readme.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Usage
2020

2121
You have to pass a `workFactory` that takes input and returns an `Observable`. This represents some work that needs to be accomplished. Whenever you call `execute()`, you pass in input that's fed to the work factory. The `Action` will subscribe to the observable and emit the `Next` events on its `elements` property. If the observable errors, the error is sent as a `Next` even on the `errors` property. Neat.
2222

23-
Actions can only execute one thing at a time. If you try to execute an action that's currently executing, you'll get an error. The `executing` property sends `true` and `false` values as `Next` events.
23+
Actions can only execute one thing at a time. If you try to execute an action that's currently executing, you'll get an error. The `isExecuting` property sends `true` and `false` values as `Next` events.
2424

2525
```swift
2626
action: Action<String, Bool> = Action(workFactory: { input in
@@ -46,19 +46,19 @@ action: Action<String, Bool> = Action(enabledIf: validEmailAddress, workFactory:
4646

4747
Now `execute()` only does the work if the email address is valid. Super cool!
4848

49-
Note that `enabledIf` isn't the same as the `enabled` property. You pass in `enabledIf` and the action uses that, and its current executing state, to determine if it's currently enabled.
49+
Note that `enabledIf` isn't the same as the `isEnabled` property. You pass in `enabledIf` and the action uses that, and its current executing state, to determine if it's currently enabled.
5050

5151
What's _really_ cool is the `UIButton` extension. It accepts a `CocoaAction`, which is just `Action<Void, Void>`.
5252

5353
```swift
5454
button.rx.action = action
5555
```
5656

57-
Now when the button is pressed, the action is executed. The button's `enabled` state is bound to the action's `enabled` property. That means you can feed your form-validation logic into the action as a signal, and your button's enabled state is handled for you. Also, the user can't press the button again before the action is done executing, since it only handles one thing at a time. Cool. Check out [this code example of CocoaAction _in_ action](https://github.com/artsy/eidolon/blob/cb31168fa29dcc7815fd4a2e30e7c000bd1820ce/Kiosk/Bid%20Fulfillment/GenericFormValidationViewModel.swift).
57+
Now when the button is pressed, the action is executed. The button's `isEnabled` state is bound to the action's `isEnabled` property. That means you can feed your form-validation logic into the action as a signal, and your button's enabled state is handled for you. Also, the user can't press the button again before the action is done executing, since it only handles one thing at a time. Cool. Check out [this code example of CocoaAction _in_ action](https://github.com/artsy/eidolon/blob/cb31168fa29dcc7815fd4a2e30e7c000bd1820ce/Kiosk/Bid%20Fulfillment/GenericFormValidationViewModel.swift).
5858

5959
If you'd like to use `Action` to do a complex operation such as file download with download progress report (to update progress bar in the UI for example) you'd use `Action<Void, Int>` instead of `CocoaAction`. Out of the box `CocoaAction` can't emit progress values, your own `Action<Void, Int>` will do that. For details refer to [this article](http://www.sm-cloud.com/rxswift-action/).
6060

61-
If your scenario involves many buttons that needs to trigger the same `Action` providing different input, you can use `bindTo` on each `UIButton` with a closure that returns correct input.
61+
If your scenario involves many buttons that needs to trigger the same `Action` providing different input, you can use `bind(to:)` on each `UIButton` with a closure that returns correct input.
6262

6363
```swift
6464
let button1 = UIButton()
@@ -68,13 +68,13 @@ let action = Action<String,String> { input in
6868
print(input)
6969
return .just(input)
7070
}
71-
button1.rx.bindTo(action) {_ in return "Hello"}
72-
button2.rx.bindTo(action) {_ in return "Goodbye"}
71+
button1.rx.bind(to: action) {_ in return "Hello"}
72+
button2.rx.bind(to: action) {_ in return "Goodbye"}
7373
```
7474

7575
`button1` and `button2` are sharing the same `Action`, but they are feeding it with different input (`Hello` and `Goodbye` that will be printed for corresponding tap).
7676

77-
A more complex use case can be a single action related to a `UIViewController` that manages your navigation, error handling and loading state. With this approach, you can have as many `UIButton`s (or `UIBarButtonItem`s) as you want and subscribe to `executing`, `errors` and `elements` once and in a single common place.
77+
A more complex use case can be a single action related to a `UIViewController` that manages your navigation, error handling and loading state. With this approach, you can have as many `UIButton`s (or `UIBarButtonItem`s) as you want and subscribe to `isExecuting`, `errors` and `elements` once and in a single common place.
7878

7979
There's also a really cool extension on `UIAlertAction`, used by [`UIAlertController`](http://ashfurrow.com/blog/uialertviewcontroller-example/). One catch: because of the limitations of that class, you can't instantiate it with the normal initializer. Instead, call this class method:
8080

Diff for: Sources/Action/Action.swift

+19-12
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ When this excuted via execute() or inputs subject, it passes its parameter to th
2222
public final class Action<Input, Element> {
2323
public typealias WorkFactory = (Input) -> Observable<Element>
2424

25-
public let _enabledIf: Observable<Bool>
26-
public let workFactory: WorkFactory
27-
2825
/// Inputs that triggers execution of action.
2926
/// This subject also includes inputs as aguments of execute().
3027
/// All inputs are always appear in this subject even if the action is not enabled.
@@ -40,7 +37,7 @@ public final class Action<Input, Element> {
4037
public let elements: Observable<Element>
4138

4239
/// Whether or not we're currently executing.
43-
public let executing: Observable<Bool>
40+
public let isExecuting: Observable<Bool>
4441

4542
/// Observables returned by the workFactory.
4643
/// Useful for sending results back from work being completed
@@ -50,7 +47,7 @@ public final class Action<Input, Element> {
5047
/// Whether or not we're enabled. Note that this is a *computed* sequence
5148
/// property based on enabledIf initializer and if we're currently executing.
5249
/// Always observed on MainScheduler.
53-
public let enabled: Observable<Bool>
50+
public let isEnabled: Observable<Bool>
5451

5552
private let disposeBag = DisposeBag()
5653

@@ -67,17 +64,14 @@ public final class Action<Input, Element> {
6764
enabledIf: Observable<Bool> = Observable.just(true),
6865
workFactory: @escaping WorkFactory) {
6966

70-
self._enabledIf = enabledIf
71-
self.workFactory = workFactory
72-
7367
let enabledSubject = BehaviorSubject<Bool>(value: false)
74-
enabled = enabledSubject.asObservable()
68+
isEnabled = enabledSubject.asObservable()
7569

7670
let errorsSubject = PublishSubject<ActionError>()
7771
errors = errorsSubject.asObservable()
7872

7973
executionObservables = inputs
80-
.withLatestFrom(enabled) { input, enabled in (input, enabled) }
74+
.withLatestFrom(isEnabled) { input, enabled in (input, enabled) }
8175
.flatMap { input, enabled -> Observable<Observable<Element>> in
8276
if enabled {
8377
return Observable.of(workFactory(input)
@@ -93,7 +87,7 @@ public final class Action<Input, Element> {
9387
elements = executionObservables
9488
.flatMap { $0.catchError { _ in Observable.empty() } }
9589

96-
executing = executionObservables.flatMap {
90+
isExecuting = executionObservables.flatMap {
9791
execution -> Observable<Bool> in
9892
let execution = execution
9993
.flatMap { _ in Observable<Bool>.empty() }
@@ -107,7 +101,7 @@ public final class Action<Input, Element> {
107101
.share(replay: 1, scope: .forever)
108102

109103
Observable
110-
.combineLatest(executing, enabledIf) { !$0 && $1 }
104+
.combineLatest(isExecuting, enabledIf) { !$0 && $1 }
111105
.bind(to: enabledSubject)
112106
.disposed(by: disposeBag)
113107
}
@@ -135,3 +129,16 @@ public final class Action<Input, Element> {
135129
return subject.asObservable()
136130
}
137131
}
132+
133+
// MARK: Deprecated
134+
extension Action {
135+
@available(*, deprecated, renamed: "isExecuting")
136+
public var executing: Observable<Bool> {
137+
return isExecuting
138+
}
139+
140+
@available(*, deprecated, renamed: "isEnabled")
141+
public var enabled: Observable<Bool> {
142+
return isEnabled
143+
}
144+
}

Diff for: Sources/Action/CommonUI/Button+Action.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public extension Reactive where Base: Button {
3131
// Set up new bindings, if applicable.
3232
if let action = newValue {
3333
action
34-
.enabled
34+
.isEnabled
3535
.bind(to: self.isEnabled)
3636
.disposed(by: self.base.actionDisposeBag)
3737

Diff for: Sources/Action/CommonUI/Control+Action.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public extension Reactive where Base: Control {
2626

2727
// Bind the enabled state of the control to the enabled state of the action
2828
action
29-
.enabled
29+
.isEnabled
3030
.bind(to: self.isEnabled)
3131
.disposed(by: self.base.actionDisposeBag)
3232
}

Diff for: Sources/Action/UIKitExtensions/UIAlertAction+Action.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ public extension Reactive where Base: UIAlertAction {
3535
// Set up new bindings, if applicable.
3636
if let action = newValue {
3737
action
38-
.enabled
39-
.bind(to: self.enabled)
38+
.isEnabled
39+
.bind(to: self.isEnabled)
4040
.disposed(by: self.base.actionDisposeBag)
4141
}
4242
}
4343
}
4444

45-
public var enabled: AnyObserver<Bool> {
45+
public var isEnabled: AnyObserver<Bool> {
4646
return AnyObserver { [weak base] event in
4747
MainScheduler.ensureExecutingOnScheduler()
4848

Diff for: Sources/Action/UIKitExtensions/UIBarButtonItem+Action.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public extension Reactive where Base: UIBarButtonItem {
2626
// Set up new bindings, if applicable.
2727
if let action = newValue {
2828
action
29-
.enabled
29+
.isEnabled
3030
.bind(to: self.isEnabled)
3131
.disposed(by: self.base.actionDisposeBag)
3232

@@ -47,7 +47,7 @@ public extension Reactive where Base: UIBarButtonItem {
4747
.disposed(by: self.base.actionDisposeBag)
4848

4949
action
50-
.enabled
50+
.isEnabled
5151
.bind(to: self.isEnabled)
5252
.disposed(by: self.base.actionDisposeBag)
5353
}

Diff for: Tests/ActionTests/ActionTests.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ class ActionTests: QuickSpec {
7373
.bind(to: errors)
7474
.disposed(by: disposeBag)
7575

76-
action.enabled
76+
action.isEnabled
7777
.bind(to: enabled)
7878
.disposed(by: disposeBag)
7979

80-
action.executing
80+
action.isExecuting
8181
.bind(to: executing)
8282
.disposed(by: disposeBag)
8383

@@ -89,8 +89,8 @@ class ActionTests: QuickSpec {
8989
action.inputs.subscribe().disposed(by: disposeBag)
9090
action.elements.subscribe().disposed(by: disposeBag)
9191
action.errors.subscribe().disposed(by: disposeBag)
92-
action.enabled.subscribe().disposed(by: disposeBag)
93-
action.executing.subscribe().disposed(by: disposeBag)
92+
action.isEnabled.subscribe().disposed(by: disposeBag)
93+
action.isExecuting.subscribe().disposed(by: disposeBag)
9494
action.executionObservables.subscribe().disposed(by: disposeBag)
9595
}
9696

0 commit comments

Comments
 (0)