-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathObservableViewModelPublisher.swift
94 lines (75 loc) · 3.03 KB
/
ObservableViewModelPublisher.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
//
// ObservableViewModelPublisher.swift
// KMPObservableViewModelCore
//
// Created by Rick Clephas on 20/09/2023.
//
import Combine
import KMPObservableViewModelCoreObjC
/// Publisher for `ObservableViewModel` that connects to the `ViewModelScope`.
public final class ObservableViewModelPublisher: Publisher {
public typealias Output = Void
public typealias Failure = Never
internal weak var viewModel: (any ViewModel)?
private let publisher = ObservableObjectPublisher()
private var objectWillChangeCancellable: AnyCancellable? = nil
internal init(_ viewModel: any ViewModel, _ objectWillChange: ObservableObjectPublisher) {
self.viewModel = viewModel
viewModel.viewModelScope.setSendObjectWillChange { [weak self] in
self?.publisher.send()
}
objectWillChangeCancellable = objectWillChange.sink { [weak self] _ in
self?.publisher.send()
}
}
public func receive<S>(subscriber: S) where S : Subscriber, Never == S.Failure, Void == S.Input {
viewModel?.viewModelScope.increaseSubscriptionCount()
publisher.receive(subscriber: ObservableViewModelSubscriber(self, subscriber))
}
deinit {
guard let viewModel else { return }
if let cancellable = viewModel as? Cancellable {
cancellable.cancel()
}
viewModel.clear()
}
}
/// Subscriber for `ObservableViewModelPublisher` that creates `ObservableViewModelSubscription`s.
private class ObservableViewModelSubscriber<S>: Subscriber where S : Subscriber, Never == S.Failure, Void == S.Input {
typealias Input = Void
typealias Failure = Never
private let publisher: ObservableViewModelPublisher
private let subscriber: S
init(_ publisher: ObservableViewModelPublisher, _ subscriber: S) {
self.publisher = publisher
self.subscriber = subscriber
}
func receive(subscription: Subscription) {
subscriber.receive(subscription: ObservableViewModelSubscription(publisher, subscription))
}
func receive(_ input: Void) -> Subscribers.Demand {
subscriber.receive(input)
}
func receive(completion: Subscribers.Completion<Never>) {
subscriber.receive(completion: completion)
}
}
/// Subscription for `ObservableViewModelPublisher` that decreases the subscription count upon cancellation.
private class ObservableViewModelSubscription: Subscription {
private let publisher: ObservableViewModelPublisher
private let subscription: Subscription
init(_ publisher: ObservableViewModelPublisher, _ subscription: Subscription) {
self.publisher = publisher
self.subscription = subscription
}
func request(_ demand: Subscribers.Demand) {
subscription.request(demand)
}
private var cancelled = false
func cancel() {
subscription.cancel()
guard !cancelled else { return }
cancelled = true
publisher.viewModel?.viewModelScope.decreaseSubscriptionCount()
}
}