forked from ReactiveCocoa/ReactiveSwift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Observer.swift
133 lines (117 loc) · 3.56 KB
/
Observer.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//
// Observer.swift
// ReactiveSwift
//
// Created by Andy Matuschak on 10/2/15.
// Copyright © 2015 GitHub. All rights reserved.
//
extension Signal {
/// An Observer is a simple wrapper around a function which can receive Events
/// (typically from a Signal).
public final class Observer {
public typealias Action = (Event) -> Void
private let _send: Action
/// Whether the observer should send an `interrupted` event as it deinitializes.
private let interruptsOnDeinit: Bool
/// An initializer that accepts a closure accepting an event for the
/// observer.
///
/// - parameters:
/// - action: A closure to lift over received event.
/// - interruptsOnDeinit: `true` if the observer should send an `interrupted`
/// event as it deinitializes. `false` otherwise.
internal init(action: @escaping Action, interruptsOnDeinit: Bool) {
self._send = action
self.interruptsOnDeinit = interruptsOnDeinit
}
/// An initializer that accepts a closure accepting an event for the
/// observer.
///
/// - parameters:
/// - action: A closure to lift over received event.
public init(_ action: @escaping Action) {
self._send = action
self.interruptsOnDeinit = false
}
/// An initializer that accepts closures for different event types.
///
/// - parameters:
/// - value: Optional closure executed when a `value` event is observed.
/// - failed: Optional closure that accepts an `Error` parameter when a
/// failed event is observed.
/// - completed: Optional closure executed when a `completed` event is
/// observed.
/// - interruped: Optional closure executed when an `interrupted` event is
/// observed.
public convenience init(
value: ((Value) -> Void)? = nil,
failed: ((Error) -> Void)? = nil,
completed: (() -> Void)? = nil,
interrupted: (() -> Void)? = nil
) {
self.init { event in
switch event {
case let .value(v):
value?(v)
case let .failed(error):
failed?(error)
case .completed:
completed?()
case .interrupted:
interrupted?()
}
}
}
internal convenience init(mappingInterruptedToCompleted observer: Signal<Value, Error>.Observer) {
self.init { event in
switch event {
case .value, .completed, .failed:
observer.send(event)
case .interrupted:
observer.sendCompleted()
}
}
}
deinit {
if interruptsOnDeinit {
// Since `Signal` would ensure that only one terminal event would ever be
// sent for any given `Signal`, we do not need to assert any condition
// here.
_send(.interrupted)
}
}
/// Puts an event into `self`.
public func send(_ event: Event) {
_send(event)
}
/// Puts a `value` event into `self`.
///
/// - parameters:
/// - value: A value sent with the `value` event.
public func send(value: Value) {
_send(.value(value))
}
/// Puts a failed event into `self`.
///
/// - parameters:
/// - error: An error object sent with failed event.
public func send(error: Error) {
_send(.failed(error))
}
/// Puts a `completed` event into `self`.
public func sendCompleted() {
_send(.completed)
}
/// Puts an `interrupted` event into `self`.
public func sendInterrupted() {
_send(.interrupted)
}
}
}
/// FIXME: Cannot be placed in `Deprecations+Removal.swift` if compiling with
/// Xcode 9.2.
extension Signal.Observer {
/// An action that will be performed upon arrival of the event.
@available(*, unavailable, renamed:"send(_:)")
public var action: Action { fatalError() }
}