Skip to content

Commit fa91e3a

Browse files
committed
Deprecates Variable in favor of BehaviorRelay.
1 parent 95a51a6 commit fa91e3a

20 files changed

+278
-124
lines changed

.jazzy.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,18 @@ custom_categories:
3232
- DispatchQueue+Extensions
3333
- name: RxCocoa/Traits
3434
children:
35+
- BehaviorRelay
3536
- ControlEvent
3637
- ControlProperty
3738
- PublishRelay
3839
- name: RxCocoa/Traits/Driver
3940
children:
41+
- BehaviorRelay+Driver
4042
- ControlEvent+Driver
4143
- ControlProperty+Driver
4244
- Driver+Subscription
4345
- Driver
4446
- ObservableConvertibleType+Driver
45-
- Variable+Driver
4647
- name: RxCocoa/Traits/SharedSequence
4748
children:
4849
- ObservableConvertibleType+SharedSequence
@@ -292,7 +293,6 @@ custom_categories:
292293
- PublishSubject
293294
- ReplaySubject
294295
- SubjectType
295-
- Variable
296296
- name: RxSwift/SwiftSupport
297297
children:
298298
- SwiftSupport

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import PackageDescription
44

5-
let buildTests = false
5+
let buildTests = true
66

77
func filterNil<T>(_ array: [T?]) -> [T] {
88
return array.flatMap { $0 }

Rx.xcodeproj/project.pbxproj

Lines changed: 21 additions & 21 deletions
Large diffs are not rendered by default.

RxCocoa/Deprecated.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import RxSwift
1111
#endif
1212

13+
import Dispatch
14+
1315
extension ObservableType {
1416

1517
/**
@@ -262,6 +264,8 @@ extension Variable {
262264
}
263265
}
264266

267+
#if !os(Linux)
268+
265269
extension DelegateProxy {
266270
@available(*, unavailable, renamed: "assignedProxy(for:)")
267271
public static func assignedProxyFor(_ object: ParentObject) -> Delegate? {
@@ -274,6 +278,8 @@ extension DelegateProxy {
274278
}
275279
}
276280

281+
#endif
282+
277283
/**
278284
Observer that enforces interface binding rules:
279285
* can't bind errors (in debug builds binding of errors causes `fatalError` in release builds errors are being logged)
@@ -393,3 +399,52 @@ extension Reactive where Base: UIImageView {
393399
}
394400
}
395401
#endif
402+
403+
#if !RX_NO_MODULE
404+
import RxSwift
405+
#endif
406+
407+
extension Variable {
408+
/// Converts `Variable` to `Driver` trait.
409+
///
410+
/// - returns: Driving observable sequence.
411+
public func asDriver() -> Driver<E> {
412+
let source = self.asObservable()
413+
.observeOn(DriverSharingStrategy.scheduler)
414+
return Driver(source)
415+
}
416+
}
417+
418+
419+
private let errorMessage = "`drive*` family of methods can be only called from `MainThread`.\n" +
420+
"This is required to ensure that the last replayed `Driver` element is delivered on `MainThread`.\n"
421+
422+
extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingStrategy {
423+
/**
424+
Creates new subscription and sends elements to variable.
425+
This method can be only called from `MainThread`.
426+
427+
- parameter variable: Target variable for sequence elements.
428+
- returns: Disposable object that can be used to unsubscribe the observer from the variable.
429+
*/
430+
public func drive(_ variable: Variable<E>) -> Disposable {
431+
MainScheduler.ensureExecutingOnScheduler(errorMessage: errorMessage)
432+
return drive(onNext: { e in
433+
variable.value = e
434+
})
435+
}
436+
437+
/**
438+
Creates new subscription and sends elements to variable.
439+
This method can be only called from `MainThread`.
440+
441+
- parameter variable: Target variable for sequence elements.
442+
- returns: Disposable object that can be used to unsubscribe the observer from the variable.
443+
*/
444+
public func drive(_ variable: Variable<E?>) -> Disposable {
445+
MainScheduler.ensureExecutingOnScheduler(errorMessage: errorMessage)
446+
return drive(onNext: { e in
447+
variable.value = e
448+
})
449+
}
450+
}

RxCocoa/Traits/BehaviorRelay.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// BehaviorRelay.swift
3+
// RxCocoa
4+
//
5+
// Created by Krunoslav Zaher on 10/7/17.
6+
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
7+
//
8+
9+
#if !RX_NO_MODULE
10+
import RxSwift
11+
#endif
12+
13+
/// BehaviorRelay is a wrapper for `BehaviorSubject`.
14+
///
15+
/// Unlike `BehaviorSubject` it can't terminate with error or completed.
16+
public final class BehaviorRelay<Element>: ObservableType {
17+
public typealias E = Element
18+
19+
private let _subject: BehaviorSubject<Element>
20+
21+
// Accepts `event` and emits it to subscribers
22+
public func accept(_ event: Element) {
23+
_subject.onNext(event)
24+
}
25+
26+
/// Current value of behavior subject
27+
public var value: Element {
28+
// this try! is ok because subject can't error out or be disposed
29+
return try! _subject.value()
30+
}
31+
32+
/// Initializes variable with initial value.
33+
public init(value: Element) {
34+
_subject = BehaviorSubject(value: value)
35+
}
36+
37+
/// Subscribes observer
38+
public func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
39+
return _subject.subscribe(observer)
40+
}
41+
42+
/// - returns: Canonical interface for push style sequence
43+
public func asObservable() -> Observable<Element> {
44+
return _subject.asObservable()
45+
}
46+
}

RxCocoa/Traits/ControlEvent.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//
88

99
#if !RX_NO_MODULE
10-
import RxSwift
10+
import RxSwift
1111
#endif
1212

1313
/// Protocol that enables extension of `ControlEvent`.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// BehaviorRelay+Driver.swift
3+
// RxCocoa
4+
//
5+
// Created by Krunoslav Zaher on 10/7/17.
6+
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
7+
//
8+
9+
#if !RX_NO_MODULE
10+
import RxSwift
11+
#endif
12+
13+
extension BehaviorRelay {
14+
/// Converts `BehaviorRelay` to `Driver`.
15+
///
16+
/// - returns: Observable sequence.
17+
public func asDriver() -> Driver<Element> {
18+
let source = self.asObservable()
19+
.observeOn(DriverSharingStrategy.scheduler)
20+
return SharedSequence(source)
21+
}
22+
}

RxCocoa/Traits/Driver/Driver+Subscription.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,16 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt
4343
}
4444

4545
/**
46-
Creates new subscription and sends elements to variable.
46+
Creates new subscription and sends elements to `BehaviorRelay`.
4747
This method can be only called from `MainThread`.
4848

4949
- parameter variable: Target variable for sequence elements.
5050
- returns: Disposable object that can be used to unsubscribe the observer from the variable.
5151
*/
52-
public func drive(_ variable: Variable<E>) -> Disposable {
52+
public func drive(_ relay: BehaviorRelay<E>) -> Disposable {
5353
MainScheduler.ensureExecutingOnScheduler(errorMessage: errorMessage)
5454
return drive(onNext: { e in
55-
variable.value = e
55+
relay.accept(e)
5656
})
5757
}
5858

@@ -63,10 +63,10 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt
6363
- parameter variable: Target variable for sequence elements.
6464
- returns: Disposable object that can be used to unsubscribe the observer from the variable.
6565
*/
66-
public func drive(_ variable: Variable<E?>) -> Disposable {
66+
public func drive(_ relay: BehaviorRelay<E?>) -> Disposable {
6767
MainScheduler.ensureExecutingOnScheduler(errorMessage: errorMessage)
6868
return drive(onNext: { e in
69-
variable.value = e
69+
relay.accept(e)
7070
})
7171
}
7272

RxCocoa/Traits/Driver/Variable+Driver.swift

Lines changed: 0 additions & 22 deletions
This file was deleted.

RxCocoa/Traits/PublishRelay.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@
66
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
77
//
88

9-
import Dispatch
109
#if !RX_NO_MODULE
1110
import RxSwift
1211
#endif
1312

1413
/// PublishRelay is a wrapper for `PublishSubject`.
1514
///
16-
/// Unlike `PublishSubject` it can't terminate with error.
17-
/// it will complete it's observable sequence (`asObservable`).
15+
/// Unlike `PublishSubject` it can't terminate with error or completed.
1816
public final class PublishRelay<Element>: ObservableType {
1917
public typealias E = Element
2018

RxSwift/Deprecated.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,63 @@ extension ObservableType {
151151
return self.share(replay: bufferSize, scope: .forever)
152152
}
153153
}
154+
155+
/// Variable is a wrapper for `BehaviorSubject`.
156+
///
157+
/// Unlike `BehaviorSubject` it can't terminate with error, and when variable is deallocated
158+
/// it will complete its observable sequence (`asObservable`).
159+
public final class Variable<Element> {
160+
161+
public typealias E = Element
162+
163+
private let _subject: BehaviorSubject<Element>
164+
165+
private var _lock = SpinLock()
166+
167+
// state
168+
private var _value: E
169+
170+
#if DEBUG
171+
fileprivate let _synchronizationTracker = SynchronizationTracker()
172+
#endif
173+
174+
/// Gets or sets current value of variable.
175+
///
176+
/// Whenever a new value is set, all the observers are notified of the change.
177+
///
178+
/// Even if the newly set value is same as the old value, observers are still notified for change.
179+
public var value: E {
180+
get {
181+
_lock.lock(); defer { _lock.unlock() }
182+
return _value
183+
}
184+
set(newValue) {
185+
#if DEBUG
186+
_synchronizationTracker.register(synchronizationErrorMessage: .variable)
187+
defer { _synchronizationTracker.unregister() }
188+
#endif
189+
_lock.lock()
190+
_value = newValue
191+
_lock.unlock()
192+
193+
_subject.on(.next(newValue))
194+
}
195+
}
196+
197+
/// Initializes variable with initial value.
198+
///
199+
/// - parameter value: Initial variable value.
200+
public init(_ value: Element) {
201+
_value = value
202+
_subject = BehaviorSubject(value: value)
203+
}
204+
205+
/// - returns: Canonical interface for push style sequence
206+
public func asObservable() -> Observable<E> {
207+
return _subject
208+
}
209+
210+
deinit {
211+
_subject.on(.completed)
212+
}
213+
}

0 commit comments

Comments
 (0)