-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathQLoop.swift
95 lines (77 loc) · 2.72 KB
/
QLoop.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
public final class QLoop<Input, Output>: QLoopIterable {
public typealias Operation = QLSegment<Input, Output>.Operation
public typealias Completion = QLSegment<Input, Output>.Completion
public typealias OnChange = QLAnchor<Output>.OnChange
public typealias OnError = QLAnchor<Output>.OnError
public required init(iterator: QLoopIterating,
onFinal: @escaping OnChange,
onChange: @escaping OnChange,
onError: @escaping OnError) {
self.iterator = iterator
self.onFinal = onFinal
self.onChange = onChange
self.onError = onError
self.applyOutputObservers()
}
public var input: QLAnchor<Input> = QLAnchor<Input>()
public var output: QLAnchor<Output> = QLAnchor<Output>() {
didSet { applyOutputObservers() }
}
private var lastValue: Output? = nil
public func perform() {
self.perform(nil)
}
public func perform(_ inputValue: Input?) {
if let iterator = self.iterator as? QLoopIteratingResettable {
iterator.reset()
}
self.input.value = inputValue
}
public func iteration() {
self.input.value = nil
}
public func iterationFromLastOutput() {
self.input.value = (self.lastValue as? Input)
}
public var discontinue: Bool = false
public var shouldResume: Bool = false
public var onFinal: OnChange
public var onChange: OnChange
public var onError: OnError
public var iterator: QLoopIterating
public func bind(path: QLPath<Input, Output>) {
self.input = path.input
self.output = path.output
}
public func bind(segment: QLSegment<Input, Output>) {
segment.output = self.output
self.input = segment.input
}
public func destroy() {
self.input = QLAnchor<Input>()
self.output = QLAnchor<Output>()
}
public func findSegments(with operationId: AnyHashable) -> [AnySegment] {
return output.inputSegment?.findSegments(with: operationId) ?? []
}
public func describeOperationPath() -> String {
return output.inputSegment?.describeOperationPath() ?? ""
}
public func operationPath() -> QLoopOperationPath {
return output.inputSegment?.operationPath() ?? []
}
private func applyOutputObservers() {
self.output.onChange = ({
self.lastValue = $0
self.onChange($0)
if (self.iterator.iterate(self) == false) {
self.onFinal($0)
}
})
self.output.onError = ({
self.onError($0)
self.discontinue = !self.shouldResume
let _ = self.iterator.iterate(self)
})
}
}