Skip to content

Commit a06f740

Browse files
committed
Moves Action to be non-optional in bindTo() functions.
1 parent 9185c46 commit a06f740

File tree

4 files changed

+54
-20
lines changed

4 files changed

+54
-20
lines changed

Sources/Action/UIKitExtensions/UIBarButtonItem+Action.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,8 @@ public extension Reactive where Base: UIBarButtonItem {
3838
}
3939
}
4040

41-
public func bindTo<Input, Output>(action: Action<Input, Output>?, inputTransform: @escaping (Base) -> (Input)) {
42-
self.base.resetActionDisposeBag()
43-
44-
guard let action = action else {
45-
return
46-
}
41+
public func bindTo<Input, Output>(action: Action<Input, Output>, inputTransform: @escaping (Base) -> (Input)) {
42+
unbindAction()
4743

4844
self.tap
4945
.map { inputTransform(self.base) }
@@ -56,9 +52,13 @@ public extension Reactive where Base: UIBarButtonItem {
5652
.addDisposableTo(self.base.actionDisposeBag)
5753
}
5854

59-
public func bindTo<Input, Output>(action: Action<Input, Output>?, input: Input) {
55+
public func bindTo<Input, Output>(action: Action<Input, Output>, input: Input) {
6056
self.bindTo(action: action) { _ in input}
6157
}
62-
58+
59+
/// Unbinds any existing action, disposing of all subscriptions.
60+
public func unbindAction() {
61+
self.base.resetActionDisposeBag()
62+
}
6363
}
6464
#endif

Sources/Action/UIKitExtensions/UIButton+Rx.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ public extension Reactive where Base: UIButton {
5454

5555
/// Binds enabled state of action to button, and subscribes to rx_tap to execute action with given input transform.
5656
/// These subscriptions are managed in a private, inaccessible dispose bag. To cancel
57-
/// them, call bindToAction with another action or nil.
58-
public func bindTo<Input, Output>(action:Action<Input, Output>?, inputTransform: @escaping (Base) -> (Input)) {
57+
/// them, call bindToAction with another action or call unbindAction().
58+
public func bindTo<Input, Output>(action:Action<Input, Output>, inputTransform: @escaping (Base) -> (Input)) {
5959
// This effectively disposes of any existing subscriptions.
60+
unbindAction()
6061

6162
// Technically, this file is only included on tv/iOS platforms,
6263
// so this optional will never be nil. But let's be safe 😉
@@ -76,8 +77,8 @@ public extension Reactive where Base: UIButton {
7677

7778
/// Binds enabled state of action to button, and subscribes to rx_tap to execute action with given input value.
7879
/// These subscriptions are managed in a private, inaccessible dispose bag. To cancel
79-
/// them, call bindToAction with another action or nil.
80-
public func bindTo<Input, Output>(action: Action<Input, Output>?, input: Input) {
80+
/// them, call bindToAction with another action or call unbindAction().
81+
public func bindTo<Input, Output>(action: Action<Input, Output>, input: Input) {
8182
self.bindTo(action: action) { _ in input }
8283
}
8384
}

Sources/Action/UIKitExtensions/UIControl+Rx.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,10 @@ import RxCocoa
66
public extension Reactive where Base: UIControl {
77
/// Binds enabled state of action to control, and subscribes action's execution to provided controlEvents.
88
/// These subscriptions are managed in a private, inaccessible dispose bag. To cancel
9-
/// them, set the rx.action to nil or another action.
10-
public func bindTo<Input, Output>(action: Action<Input, Output>?, controlEvent: ControlEvent<Void>, inputTransform: @escaping (Base) -> (Input)) {
9+
/// them, set the rx.action to nil or another action, or call unbindAction().
10+
public func bindTo<Input, Output>(action: Action<Input, Output>, controlEvent: ControlEvent<Void>, inputTransform: @escaping (Base) -> (Input)) {
1111
// This effectively disposes of any existing subscriptions.
12-
self.base.resetActionDisposeBag()
13-
14-
// If no action is provided, there is nothing left to do. All previous subscriptions are disposed.
15-
guard let action = action else {
16-
return
17-
}
12+
unbindAction()
1813

1914
// For each tap event, use the inputTransform closure to provide an Input value to the action
2015
controlEvent
@@ -28,6 +23,11 @@ public extension Reactive where Base: UIControl {
2823
.bindTo(self.isEnabled)
2924
.addDisposableTo(self.base.actionDisposeBag)
3025
}
26+
27+
/// Unbinds any existing action, disposing of all subscriptions.
28+
public func unbindAction() {
29+
self.base.resetActionDisposeBag()
30+
}
3131
}
3232

3333
#endif

Tests/ActionTests/BindToTests.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,38 @@ class BindToTests: QuickSpec {
6464

6565
expect(called).toEventually( beTrue() )
6666
}
67+
68+
describe("unbinding") {
69+
it("unbinds actions for UIButton") {
70+
let button = UIButton()
71+
let action = Action<String, String>(workFactory: { _ in
72+
assertionFailure()
73+
return .empty()
74+
})
75+
button.rx.bindTo(action: action, input: "Hi there!")
76+
// Setting the action has an asynchronous effect of adding a target.
77+
expect(button.allTargets).toEventuallyNot( beEmpty() )
78+
79+
button.rx.unbindAction()
80+
button.test_executeTap()
81+
82+
expect(button.allTargets).toEventually( beEmpty() )
83+
}
84+
85+
it("actives a UIBarButtonItem") {
86+
var called = false
87+
let item = UIBarButtonItem()
88+
let action = Action<String, String>(workFactory: { _ in
89+
called = true
90+
return .empty()
91+
})
92+
item.rx.bindTo(action: action, input: "Hi there!")
93+
94+
item.rx.unbindAction()
95+
_ = item.target?.perform(item.action!, with: item)
96+
97+
expect(called).to( beFalse() )
98+
}
99+
}
67100
}
68101
}

0 commit comments

Comments
 (0)