Skip to content

Commit 2dc37a2

Browse files
committed
Introduce SubscriptionCount class
1 parent 599b04d commit 2dc37a2

File tree

8 files changed

+68
-35
lines changed

8 files changed

+68
-35
lines changed

KMPObservableViewModelCore/ObservableViewModelPublisher.swift

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ public final class ObservableViewModelPublisher: Publisher {
1414
public typealias Failure = Never
1515

1616
internal weak var viewModel: (any ViewModel)?
17+
private let subscriptionCount: any SubscriptionCount
1718

1819
private let publisher = ObservableObjectPublisher()
1920
private var objectWillChangeCancellable: AnyCancellable? = nil
2021

2122
internal init(_ viewModel: any ViewModel, _ objectWillChange: ObservableObjectPublisher) {
2223
self.viewModel = viewModel
24+
self.subscriptionCount = viewModel.viewModelScope.subscriptionCount
2325
viewModel.viewModelScope.setSendObjectWillChange { [weak self] in
2426
self?.publisher.send()
2527
}
@@ -29,8 +31,8 @@ public final class ObservableViewModelPublisher: Publisher {
2931
}
3032

3133
public func receive<S>(subscriber: S) where S : Subscriber, Never == S.Failure, Void == S.Input {
32-
viewModel?.viewModelScope.increaseSubscriptionCount()
33-
publisher.receive(subscriber: ObservableViewModelSubscriber(self, subscriber))
34+
subscriptionCount.increase()
35+
publisher.receive(subscriber: ObservableViewModelSubscriber(subscriptionCount, subscriber))
3436
}
3537

3638
deinit {
@@ -47,16 +49,16 @@ private class ObservableViewModelSubscriber<S>: Subscriber where S : Subscriber,
4749
typealias Input = Void
4850
typealias Failure = Never
4951

50-
private let publisher: ObservableViewModelPublisher
52+
private let subscriptionCount: any SubscriptionCount
5153
private let subscriber: S
5254

53-
init(_ publisher: ObservableViewModelPublisher, _ subscriber: S) {
54-
self.publisher = publisher
55+
init(_ subscriptionCount: any SubscriptionCount, _ subscriber: S) {
56+
self.subscriptionCount = subscriptionCount
5557
self.subscriber = subscriber
5658
}
5759

5860
func receive(subscription: Subscription) {
59-
subscriber.receive(subscription: ObservableViewModelSubscription(publisher, subscription))
61+
subscriber.receive(subscription: ObservableViewModelSubscription(subscriptionCount, subscription))
6062
}
6163

6264
func receive(_ input: Void) -> Subscribers.Demand {
@@ -71,24 +73,21 @@ private class ObservableViewModelSubscriber<S>: Subscriber where S : Subscriber,
7173
/// Subscription for `ObservableViewModelPublisher` that decreases the subscription count upon cancellation.
7274
private class ObservableViewModelSubscription: Subscription {
7375

74-
private let publisher: ObservableViewModelPublisher
76+
private var subscriptionCount: (any SubscriptionCount)?
7577
private let subscription: Subscription
7678

77-
init(_ publisher: ObservableViewModelPublisher, _ subscription: Subscription) {
78-
self.publisher = publisher
79+
init(_ subscriptionCount: any SubscriptionCount, _ subscription: Subscription) {
80+
self.subscriptionCount = subscriptionCount
7981
self.subscription = subscription
8082
}
8183

8284
func request(_ demand: Subscribers.Demand) {
8385
subscription.request(demand)
8486
}
8587

86-
private var cancelled = false
87-
8888
func cancel() {
8989
subscription.cancel()
90-
guard !cancelled else { return }
91-
cancelled = true
92-
publisher.viewModel?.viewModelScope.decreaseSubscriptionCount()
90+
subscriptionCount?.decrease()
91+
subscriptionCount = nil
9392
}
9493
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// KMPOVMSubscriptionCount.h
3+
// KMPObservableViewModel
4+
//
5+
// Created by Rick Clephas on 09/06/2025.
6+
//
7+
8+
#ifndef KMPOVMSubscriptionCount_h
9+
#define KMPOVMSubscriptionCount_h
10+
11+
#import <Foundation/Foundation.h>
12+
13+
NS_ASSUME_NONNULL_BEGIN
14+
15+
__attribute__((swift_name("SubscriptionCount")))
16+
@protocol KMPOVMSubscriptionCount
17+
- (void)increase;
18+
- (void)decrease;
19+
@end
20+
21+
NS_ASSUME_NONNULL_END
22+
23+
#endif /* KMPOVMSubscriptionCount_h */

KMPObservableViewModelCoreObjC/KMPOVMViewModelScope.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@
99
#define KMPOVMViewModelScope_h
1010

1111
#import <Foundation/Foundation.h>
12+
#import "KMPOVMSubscriptionCount.h"
13+
14+
NS_ASSUME_NONNULL_BEGIN
1215

1316
__attribute__((swift_name("ViewModelScope")))
1417
@protocol KMPOVMViewModelScope
15-
- (void)increaseSubscriptionCount;
16-
- (void)decreaseSubscriptionCount;
18+
@property (readonly) id<KMPOVMSubscriptionCount> subscriptionCount;
19+
1720
- (void)setSendObjectWillChange:(void (^ _Nonnull)(void))sendObjectWillChange;
1821
@end
1922

23+
NS_ASSUME_NONNULL_END
24+
2025
#endif /* KMPOVMViewModelScope_h */

KMPObservableViewModelCoreObjC/KMPObservableViewModelCoreObjC.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
// Created by Rick Clephas on 27/11/2022.
66
//
77

8+
#import "KMPOVMSubscriptionCount.h"
89
#import "KMPOVMViewModelScope.h"

kmp-observableviewmodel-core/src/appleMain/kotlin/com/rickclephas/kmp/observableviewmodel/CombinedSubscriptionCount.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ internal class CombinedSubscriptionCount private constructor(
1616
): StateFlow<Int> {
1717

1818
constructor(viewModelScope: NativeViewModelScope, stateFlow: MutableStateFlow<*>) : this(
19-
viewModelScopeCount = viewModelScope.subscriptionCount,
19+
viewModelScopeCount = viewModelScope.subscriptionCount().stateFlow,
2020
stateFlowCount = stateFlow.subscriptionCount
2121
)
2222

kmp-observableviewmodel-core/src/appleMain/kotlin/com/rickclephas/kmp/observableviewmodel/NativeViewModelScope.kt

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
package com.rickclephas.kmp.observableviewmodel
22

33
import kotlinx.coroutines.CoroutineScope
4-
import kotlinx.coroutines.flow.MutableStateFlow
5-
import kotlinx.coroutines.flow.StateFlow
6-
import kotlinx.coroutines.flow.asStateFlow
7-
import kotlinx.coroutines.flow.update
84
import platform.darwin.NSObject
95

106
/**
@@ -15,19 +11,8 @@ internal class NativeViewModelScope internal constructor(
1511
val coroutineScope: CoroutineScope
1612
): NSObject(), ViewModelScope {
1713

18-
private val _subscriptionCount = MutableStateFlow(0)
19-
/**
20-
* A [StateFlow] that emits the number of subscribers to the [ViewModel].
21-
*/
22-
val subscriptionCount: StateFlow<Int> = _subscriptionCount.asStateFlow()
23-
24-
override fun increaseSubscriptionCount() {
25-
_subscriptionCount.update { it + 1 }
26-
}
27-
28-
override fun decreaseSubscriptionCount() {
29-
_subscriptionCount.update { it - 1 }
30-
}
14+
private val _subscriptionCount = SubscriptionCount()
15+
override fun subscriptionCount(): SubscriptionCount = _subscriptionCount
3116

3217
private var sendObjectWillChange: (() -> Unit)? = null
3318

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.rickclephas.kmp.observableviewmodel
2+
3+
import com.rickclephas.kmp.observableviewmodel.objc.KMPOVMSubscriptionCountProtocol
4+
import kotlinx.coroutines.flow.MutableStateFlow
5+
import kotlinx.coroutines.flow.StateFlow
6+
import kotlinx.coroutines.flow.asStateFlow
7+
import kotlinx.coroutines.flow.update
8+
import platform.darwin.NSObject
9+
10+
/**
11+
* [KMPOVMSubscriptionCountProtocol] implementation that uses a [StateFlow] to store the subscription count.
12+
*/
13+
internal class SubscriptionCount: NSObject(), KMPOVMSubscriptionCountProtocol {
14+
15+
private val _stateFlow = MutableStateFlow(0)
16+
val stateFlow: StateFlow<Int> = _stateFlow.asStateFlow()
17+
18+
override fun increase(): Unit = _stateFlow.update { it + 1 }
19+
override fun decrease(): Unit = _stateFlow.update { it - 1 }
20+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
language = Objective-C
22
package = com.rickclephas.kmp.observableviewmodel.objc
3-
headers = KMPOVMViewModelScope.h
3+
headers = KMPOVMSubscriptionCount.h KMPOVMViewModelScope.h

0 commit comments

Comments
 (0)