@@ -225,3 +225,46 @@ This will prevent your Swift view models from being deallocated too soon.
225
225
226
226
> [ !NOTE]
227
227
> For lists, sets and dictionaries containing view models there is ` childViewModels(at:) ` .
228
+
229
+ ### Cancellable ViewModel
230
+
231
+ When subclassing your Kotlin ViewModel in Swift you might experience some issues in the way those ViewModels are cleared.
232
+
233
+ An example of such an issue is when you are using a Combine publisher to observe a Flow through KMP-NativeCoroutines:
234
+ ``` swift
235
+ import Combine
236
+ import KMPNativeCoroutinesCombine
237
+ import shared // This should be your shared KMM module
238
+
239
+ class TimeTravelViewModel : shared .TimeTravelViewModel {
240
+
241
+ private var cancellables = Set < AnyCancellable> ()
242
+
243
+ override init () {
244
+ super .init ()
245
+ createPublisher (for : currentTimeFlow)
246
+ .assertNoFailure ()
247
+ .sink { time in print (" It's \( time ) " ) }
248
+ .store (in : & cancellables)
249
+ }
250
+ }
251
+ ```
252
+
253
+ Since ` currentTimeFlow ` is a StateFlow we don't ever expect it to fail, which is why we are using the ` assertNoFailure ` .
254
+ However, in this case you'll notice that the publisher will fail with a ` JobCancellationException ` .
255
+
256
+ The problem here is that before the ` TimeTravelViewModel ` is deinited it will already be cleared.
257
+ Meaning the ` viewModelScope ` is cancelled and ` onCleared ` is called.
258
+ This results in the Combine publisher outliving the underlying StateFlow collection.
259
+
260
+ To solve such issues you should have your Swift ViewModel conform to ` Cancellable `
261
+ and perform the required cleanup in the ` cancel ` function:
262
+ ``` swift
263
+ class TimeTravelViewModel : shared .TimeTravelViewModel , Cancellable {
264
+ func cancel () {
265
+ cancellables = []
266
+ }
267
+ }
268
+ ```
269
+
270
+ KMM-ViewModel will make sure to call the ` cancel ` function before the ViewModel is being cleared.
0 commit comments