Permalink
Browse files

Deprecates `Variable` in favor of `BehaviorRelay`.

  • Loading branch information...
kzaher committed Oct 7, 2017
1 parent 95a51a6 commit fa91e3a87d06bb7c3fd3f67d0464b4cc48e30262
@@ -32,17 +32,18 @@ custom_categories:
- DispatchQueue+Extensions
- name: RxCocoa/Traits
children:
- BehaviorRelay
- ControlEvent
- ControlProperty
- PublishRelay
- name: RxCocoa/Traits/Driver
children:
- BehaviorRelay+Driver
- ControlEvent+Driver
- ControlProperty+Driver
- Driver+Subscription
- Driver
- ObservableConvertibleType+Driver
- Variable+Driver
- name: RxCocoa/Traits/SharedSequence
children:
- ObservableConvertibleType+SharedSequence
@@ -292,7 +293,6 @@ custom_categories:
- PublishSubject
- ReplaySubject
- SubjectType
- Variable
- name: RxSwift/SwiftSupport
children:
- SwiftSupport
@@ -2,7 +2,7 @@
import PackageDescription

let buildTests = false
let buildTests = true

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

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -10,6 +10,8 @@
import RxSwift
#endif

import Dispatch

extension ObservableType {

/**
@@ -262,6 +264,8 @@ extension Variable {
}
}

#if !os(Linux)

extension DelegateProxy {
@available(*, unavailable, renamed: "assignedProxy(for:)")
public static func assignedProxyFor(_ object: ParentObject) -> Delegate? {
@@ -274,6 +278,8 @@ extension DelegateProxy {
}
}

#endif

/**
Observer that enforces interface binding rules:
* 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 {
}
}
#endif

#if !RX_NO_MODULE
import RxSwift
#endif

extension Variable {
/// Converts `Variable` to `Driver` trait.
///
/// - returns: Driving observable sequence.
public func asDriver() -> Driver<E> {
let source = self.asObservable()
.observeOn(DriverSharingStrategy.scheduler)
return Driver(source)
}
}


private let errorMessage = "`drive*` family of methods can be only called from `MainThread`.\n" +
"This is required to ensure that the last replayed `Driver` element is delivered on `MainThread`.\n"

extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingStrategy {
/**
Creates new subscription and sends elements to variable.
This method can be only called from `MainThread`.
- parameter variable: Target variable for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer from the variable.
*/
public func drive(_ variable: Variable<E>) -> Disposable {
MainScheduler.ensureExecutingOnScheduler(errorMessage: errorMessage)
return drive(onNext: { e in
variable.value = e
})
}

/**
Creates new subscription and sends elements to variable.
This method can be only called from `MainThread`.
- parameter variable: Target variable for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer from the variable.
*/
public func drive(_ variable: Variable<E?>) -> Disposable {
MainScheduler.ensureExecutingOnScheduler(errorMessage: errorMessage)
return drive(onNext: { e in
variable.value = e
})
}
}
@@ -0,0 +1,46 @@
//
// BehaviorRelay.swift
// RxCocoa
//
// Created by Krunoslav Zaher on 10/7/17.
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
//
#if !RX_NO_MODULE
import RxSwift
#endif

/// BehaviorRelay is a wrapper for `BehaviorSubject`.
///
/// Unlike `BehaviorSubject` it can't terminate with error or completed.
public final class BehaviorRelay<Element>: ObservableType {
public typealias E = Element

private let _subject: BehaviorSubject<Element>

// Accepts `event` and emits it to subscribers
public func accept(_ event: Element) {
_subject.onNext(event)
}

/// Current value of behavior subject
public var value: Element {
// this try! is ok because subject can't error out or be disposed
return try! _subject.value()
}

/// Initializes variable with initial value.
public init(value: Element) {
_subject = BehaviorSubject(value: value)
}

/// Subscribes observer
public func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
return _subject.subscribe(observer)
}

/// - returns: Canonical interface for push style sequence
public func asObservable() -> Observable<Element> {
return _subject.asObservable()
}
}
@@ -7,7 +7,7 @@
//
#if !RX_NO_MODULE
import RxSwift
import RxSwift
#endif

/// Protocol that enables extension of `ControlEvent`.
@@ -0,0 +1,22 @@
//
// BehaviorRelay+Driver.swift
// RxCocoa
//
// Created by Krunoslav Zaher on 10/7/17.
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
//
#if !RX_NO_MODULE
import RxSwift
#endif

extension BehaviorRelay {
/// Converts `BehaviorRelay` to `Driver`.
///
/// - returns: Observable sequence.
public func asDriver() -> Driver<Element> {
let source = self.asObservable()
.observeOn(DriverSharingStrategy.scheduler)
return SharedSequence(source)
}
}
@@ -43,16 +43,16 @@ extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingSt
}

/**
Creates new subscription and sends elements to variable.
Creates new subscription and sends elements to `BehaviorRelay`.
This method can be only called from `MainThread`.
- parameter variable: Target variable for sequence elements.
- returns: Disposable object that can be used to unsubscribe the observer from the variable.
*/
public func drive(_ variable: Variable<E>) -> Disposable {
public func drive(_ relay: BehaviorRelay<E>) -> Disposable {
MainScheduler.ensureExecutingOnScheduler(errorMessage: errorMessage)
return drive(onNext: { e in
variable.value = e
relay.accept(e)
})
}

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

This file was deleted.

Oops, something went wrong.
@@ -6,15 +6,13 @@
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
//
import Dispatch
#if !RX_NO_MODULE
import RxSwift
#endif

/// PublishRelay is a wrapper for `PublishSubject`.
///
/// Unlike `PublishSubject` it can't terminate with error.
/// it will complete it's observable sequence (`asObservable`).
/// Unlike `PublishSubject` it can't terminate with error or completed.
public final class PublishRelay<Element>: ObservableType {
public typealias E = Element

@@ -151,3 +151,63 @@ extension ObservableType {
return self.share(replay: bufferSize, scope: .forever)
}
}

/// Variable is a wrapper for `BehaviorSubject`.
///
/// Unlike `BehaviorSubject` it can't terminate with error, and when variable is deallocated
/// it will complete its observable sequence (`asObservable`).
public final class Variable<Element> {

public typealias E = Element

private let _subject: BehaviorSubject<Element>

private var _lock = SpinLock()

// state
private var _value: E

#if DEBUG
fileprivate let _synchronizationTracker = SynchronizationTracker()
#endif

/// Gets or sets current value of variable.
///
/// Whenever a new value is set, all the observers are notified of the change.
///
/// Even if the newly set value is same as the old value, observers are still notified for change.
public var value: E {
get {
_lock.lock(); defer { _lock.unlock() }
return _value
}
set(newValue) {
#if DEBUG
_synchronizationTracker.register(synchronizationErrorMessage: .variable)
defer { _synchronizationTracker.unregister() }
#endif
_lock.lock()
_value = newValue
_lock.unlock()

_subject.on(.next(newValue))
}
}

/// Initializes variable with initial value.
///
/// - parameter value: Initial variable value.
public init(_ value: Element) {
_value = value
_subject = BehaviorSubject(value: value)
}

/// - returns: Canonical interface for push style sequence
public func asObservable() -> Observable<E> {
return _subject
}

deinit {
_subject.on(.completed)
}
}
Oops, something went wrong.

0 comments on commit fa91e3a

Please sign in to comment.