-
Hi thank you so much for creating this amazing library. I have a view that executes a long living effect (a timer). but when i tap on back to dismiss the view, the timer still executes even when the view is no longer visible. After checking it, the store is not deallocated when i tap on the back button causing the timer to still run. Are there a way so i can automatically cancel all my long living effects when my view disappears? Thank you, any help and guidance would be very helpful. Here is my sample code: @main
struct DemoApp: App {
var body: some Scene {
WindowGroup {
View1()
}
}
}
struct View1: View {
var body: some View {
NavigationView {
List {
NavigationLink("Navigate to View2", destination: View2())
}
.navigationTitle("View1")
}
}
}
struct View2: View {
private let store: Store<Void, Action> = Store(initialState: (), reducer: reducer, environment: ())
var body: some View {
Text("View2")
.onAppear {
ViewStore(store).send(.onAppear)
}
}
}
enum Action {
case onAppear
case receiveLongLivingEffect
}
let reducer = Reducer<Void, Action, Void> { _, action, _ in
switch action {
case .onAppear:
return Effect.timer(id: "id", every: 1, on: DispatchQueue.main)
.map { _ in Action.receiveLongLivingEffect }
.eraseToEffect()
case .receiveLongLivingEffect:
print(">> Receive effect")
return .none
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 8 replies
-
Hi @vctxr, if you can use version 0.39.0 or later of the library, then this can automatically be handled for you via Swift's concurrency tools. Rather than using So, rather than having an case .task:
return .run { send in
for await _ in DispatchQueue.main.timer(interval: .seconds(1)) {
await send(.receiveLongLivingEffect)
}
} And then you can .task {
await viewStore.send(.task).finish()
} Then when the view goes away this timer will automatically be cancelled and the effect torn down. I would also recommend thinking about putting a scheduler in your environment to use for the timer rather than reaching out to |
Beta Was this translation helpful? Give feedback.
Hi @vctxr, if you can use version 0.39.0 or later of the library, then this can automatically be handled for you via Swift's concurrency tools.
Rather than using
.onAppear
you need to use SwiftUI's.task
view modifier, which allows you to perform some asynchronous work when the view appears, and that work will automatically be cancelled when the view goes away.So, rather than having an
onAppear
action that uses a Combine timer, you can have a.task
action that makes use of an async/await timer:And then you can
await
sending that …