Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# master
*Please add new entries at the top.*

1. `ActionDisposable` and `SimpleDisposable` have been folded into `AnyDisposable`. (#412, kudos to @andersio)

1. `promoteErrors(_:)` has been renamed to `promoteError(_:)`. (#408, kudos to @andersio)

# 1.1.3
Expand Down
11 changes: 11 additions & 0 deletions Sources/Deprecations+Removals.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import Dispatch
import Result

// MARK: Unavailable methods in ReactiveSwift 2.0.
extension AnyDisposable {
@available(*, unavailable, renamed:"init(_:)")
public convenience init(action: @escaping () -> Void) { fatalError() }
}

extension Signal {
@available(*, unavailable, renamed:"promoteError")
public func promoteErrors<F: Swift.Error>(_: F.Type) -> Signal<Value, F> { fatalError() }
Expand Down Expand Up @@ -142,6 +147,12 @@ public func timer(interval: DispatchTimeInterval, on scheduler: DateScheduler) -
public func timer(interval: DispatchTimeInterval, on scheduler: DateScheduler, leeway: DispatchTimeInterval) -> SignalProducer<Date, NoError> { fatalError() }

// MARK: Obsolete types in ReactiveSwift 2.0.
@available(*, unavailable, renamed:"AnyDisposable")
public typealias SimpleDisposable = AnyDisposable

@available(*, unavailable, renamed:"AnyDisposable")
public typealias ActionDisposable = AnyDisposable

@available(*, unavailable, renamed:"Signal.Event")
public typealias Event<Value, Error: Swift.Error> = Signal<Value, Error>.Event

Expand Down
232 changes: 111 additions & 121 deletions Sources/Disposable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,68 +40,56 @@ extension UnsafeAtomicState where State == DisposableState {

/// A type-erased disposable that forwards operations to an underlying disposable.
public final class AnyDisposable: Disposable {
private let disposable: Disposable
private final class ActionDisposable: Disposable {
let state: UnsafeAtomicState<DisposableState>
var action: (() -> Void)?

public var isDisposed: Bool {
return disposable.isDisposed
}
var isDisposed: Bool {
return state.is(.disposed)
}

public init(_ disposable: Disposable) {
self.disposable = disposable
}
init(_ action: (() -> Void)?) {
self.state = UnsafeAtomicState(.active)
self.action = action
}

public func dispose() {
disposable.dispose()
func dispose() {
if state.tryDispose() {
action?()
action = nil
}
}
}
}

/// A disposable that only flips `isDisposed` upon disposal, and performs no other
/// work.
public final class SimpleDisposable: Disposable {
private var state = UnsafeAtomicState(DisposableState.active)
private let base: Disposable

public var isDisposed: Bool {
return state.is(.disposed)
return base.isDisposed
}

public init() {}

public func dispose() {
_ = state.tryDispose()
}

deinit {
state.deinitialize()
/// Create a disposable which runs the given action upon disposal.
///
/// - parameters:
/// - action: A closure to run when calling `dispose()`.
public init(_ action: @escaping () -> Void) {
base = ActionDisposable(action)
}
}

/// A disposable that will run an action upon disposal.
public final class ActionDisposable: Disposable {
private var action: (() -> Void)?
private var state: UnsafeAtomicState<DisposableState>

public var isDisposed: Bool {
return state.is(.disposed)
/// Create a disposable.
public init() {
base = ActionDisposable(nil)
}

/// Initialize the disposable to run the given action upon disposal.
/// Create a disposable which wraps the given disposable.
///
/// - parameters:
/// - action: A closure to run when calling `dispose()`.
public init(action: @escaping () -> Void) {
self.action = action
self.state = UnsafeAtomicState(DisposableState.active)
/// - disposable: The disposable to be wrapped.
public init(_ disposable: Disposable) {
base = disposable
}

public func dispose() {
if state.tryDispose() {
action?()
action = nil
}
}

deinit {
state.deinitialize()
base.dispose()
}
}

Expand Down Expand Up @@ -179,7 +167,7 @@ public final class CompositeDisposable: Disposable {
guard disposables != nil else { return nil }

let token = disposables!.insert(d)
return ActionDisposable { [weak self] in
return AnyDisposable { [weak self] in
self?.disposables.modify {
$0?.remove(using: token)
}
Expand All @@ -197,12 +185,51 @@ public final class CompositeDisposable: Disposable {
/// `disposable` is `nil`.
@discardableResult
public func add(_ action: @escaping () -> Void) -> Disposable? {
return add(ActionDisposable(action: action))
return add(AnyDisposable(action))
}

deinit {
state.deinitialize()
}

/// Adds the right-hand-side disposable to the left-hand-side
/// `CompositeDisposable`.
///
/// ````
/// disposable += producer
/// .filter { ... }
/// .map { ... }
/// .start(observer)
/// ````
///
/// - parameters:
/// - lhs: Disposable to add to.
/// - rhs: Disposable to add.
///
/// - returns: An instance of `DisposableHandle` that can be used to opaquely
/// remove the disposable later (if desired).
@discardableResult
public static func +=(lhs: CompositeDisposable, rhs: Disposable?) -> Disposable? {
return lhs.add(rhs)
}

/// Adds the right-hand-side `ActionDisposable` to the left-hand-side
/// `CompositeDisposable`.
///
/// ````
/// disposable += { ... }
/// ````
///
/// - parameters:
/// - lhs: Disposable to add to.
/// - rhs: Closure to add as a disposable.
///
/// - returns: An instance of `DisposableHandle` that can be used to opaquely
/// remove the disposable later (if desired).
@discardableResult
public static func +=(lhs: CompositeDisposable, rhs: @escaping () -> ()) -> Disposable? {
return lhs.add(rhs)
}
}

/// A disposable that, upon deinitialization, will automatically dispose of
Expand Down Expand Up @@ -246,6 +273,44 @@ extension ScopedDisposable where Inner == AnyDisposable {
}
}

extension ScopedDisposable where Inner == CompositeDisposable {
/// Adds the right-hand-side disposable to the left-hand-side
/// `ScopedDisposable<CompositeDisposable>`.
///
/// ````
/// disposable += { ... }
/// ````
///
/// - parameters:
/// - lhs: Disposable to add to.
/// - rhs: Disposable to add.
///
/// - returns: An instance of `DisposableHandle` that can be used to opaquely
/// remove the disposable later (if desired).
@discardableResult
public static func +=(lhs: ScopedDisposable<CompositeDisposable>, rhs: Disposable?) -> Disposable? {
return lhs.inner.add(rhs)
}

/// Adds the right-hand-side disposable to the left-hand-side
/// `ScopedDisposable<CompositeDisposable>`.
///
/// ````
/// disposable += { ... }
/// ````
///
/// - parameters:
/// - lhs: Disposable to add to.
/// - rhs: Closure to add as a disposable.
///
/// - returns: An instance of `DisposableHandle` that can be used to opaquely
/// remove the disposable later (if desired).
@discardableResult
public static func +=(lhs: ScopedDisposable<CompositeDisposable>, rhs: @escaping () -> ()) -> Disposable? {
return lhs.inner.add(rhs)
}
}

/// A disposable that disposes of its wrapped disposable, and allows its
/// wrapped disposable to be replaced.
public final class SerialDisposable: Disposable {
Expand Down Expand Up @@ -293,78 +358,3 @@ public final class SerialDisposable: Disposable {
state.deinitialize()
}
}

/// Adds the right-hand-side disposable to the left-hand-side
/// `CompositeDisposable`.
///
/// ````
/// disposable += producer
/// .filter { ... }
/// .map { ... }
/// .start(observer)
/// ````
///
/// - parameters:
/// - lhs: Disposable to add to.
/// - rhs: Disposable to add.
///
/// - returns: An instance of `DisposableHandle` that can be used to opaquely
/// remove the disposable later (if desired).
@discardableResult
public func +=(lhs: CompositeDisposable, rhs: Disposable?) -> Disposable? {
return lhs.add(rhs)
}

/// Adds the right-hand-side `ActionDisposable` to the left-hand-side
/// `CompositeDisposable`.
///
/// ````
/// disposable += { ... }
/// ````
///
/// - parameters:
/// - lhs: Disposable to add to.
/// - rhs: Closure to add as a disposable.
///
/// - returns: An instance of `DisposableHandle` that can be used to opaquely
/// remove the disposable later (if desired).
@discardableResult
public func +=(lhs: CompositeDisposable, rhs: @escaping () -> ()) -> Disposable? {
return lhs.add(rhs)
}

/// Adds the right-hand-side disposable to the left-hand-side
/// `ScopedDisposable<CompositeDisposable>`.
///
/// ````
/// disposable += { ... }
/// ````
///
/// - parameters:
/// - lhs: Disposable to add to.
/// - rhs: Disposable to add.
///
/// - returns: An instance of `DisposableHandle` that can be used to opaquely
/// remove the disposable later (if desired).
@discardableResult
public func +=(lhs: ScopedDisposable<CompositeDisposable>, rhs: Disposable?) -> Disposable? {
return lhs.inner.add(rhs)
}

/// Adds the right-hand-side disposable to the left-hand-side
/// `ScopedDisposable<CompositeDisposable>`.
///
/// ````
/// disposable += { ... }
/// ````
///
/// - parameters:
/// - lhs: Disposable to add to.
/// - rhs: Closure to add as a disposable.
///
/// - returns: An instance of `DisposableHandle` that can be used to opaquely
/// remove the disposable later (if desired).
@discardableResult
public func +=(lhs: ScopedDisposable<CompositeDisposable>, rhs: @escaping () -> ()) -> Disposable? {
return lhs.inner.add(rhs)
}
2 changes: 1 addition & 1 deletion Sources/Flatten.swift
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ extension Signal where Value: SignalProducerProtocol, Error == Value.Error {
func startNextIfNeeded() {
while let producer = state.modify({ $0.dequeue() }) {
let producerState = UnsafeAtomicState<ProducerState>(.starting)
let deinitializer = ScopedDisposable(ActionDisposable(action: producerState.deinitialize))
let deinitializer = ScopedDisposable(AnyDisposable(producerState.deinitialize))

producer.startWithSignal { signal, inner in
let handle = disposable.add(inner)
Expand Down
2 changes: 1 addition & 1 deletion Sources/FoundationExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ extension Reactive where Base: NotificationCenter {
observer.send(value: notification)
}

return ActionDisposable {
return AnyDisposable {
base.removeObserver(notificationObserver)
}
}
Expand Down
10 changes: 5 additions & 5 deletions Sources/Scheduler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public final class UIScheduler: Scheduler {
/// begins.
@discardableResult
public func schedule(_ action: @escaping () -> Void) -> Disposable? {
let disposable = SimpleDisposable()
let disposable = AnyDisposable()
let actionAndDecrement = {
if !disposable.isDisposed {
action()
Expand Down Expand Up @@ -233,7 +233,7 @@ public final class QueueScheduler: DateScheduler {
/// begins.
@discardableResult
public func schedule(_ action: @escaping () -> Void) -> Disposable? {
let d = SimpleDisposable()
let d = AnyDisposable()

queue.async {
if !d.isDisposed {
Expand Down Expand Up @@ -263,7 +263,7 @@ public final class QueueScheduler: DateScheduler {
/// before it begins.
@discardableResult
public func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? {
let d = SimpleDisposable()
let d = AnyDisposable()

queue.asyncAfter(wallDeadline: wallTime(with: date)) {
if !d.isDisposed {
Expand Down Expand Up @@ -325,7 +325,7 @@ public final class QueueScheduler: DateScheduler {
timer.setEventHandler(handler: action)
timer.resume()

return ActionDisposable {
return AnyDisposable {
timer.cancel()
}
}
Expand Down Expand Up @@ -378,7 +378,7 @@ public final class TestScheduler: DateScheduler {
scheduledActions.sort { $0.less($1) }
lock.unlock()

return ActionDisposable {
return AnyDisposable {
self.lock.lock()
self.scheduledActions = self.scheduledActions.filter { $0 !== action }
self.lock.unlock()
Expand Down
Loading