diff --git a/MobiusCore/Source/Disposables/Task+Disposable.swift b/MobiusCore/Source/Disposables/Task+Disposable.swift new file mode 100644 index 00000000..98070a8b --- /dev/null +++ b/MobiusCore/Source/Disposables/Task+Disposable.swift @@ -0,0 +1,29 @@ +// Copyright 2019-2024 Spotify AB. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +public extension Task { + + /// A disposable for use with `EffectHandler` that will cancel the task + /// + /// func handle(_ parameters: Void, _ callback: EffectCallback) -> Disposable { + /// Task { + /// + /// } + /// .asDisposable + /// } + var asDisposable: some Disposable { + AnonymousDisposable { cancel() } + } +} diff --git a/MobiusCore/Test/Task+DisposableTests.swift b/MobiusCore/Test/Task+DisposableTests.swift new file mode 100644 index 00000000..73e7e071 --- /dev/null +++ b/MobiusCore/Test/Task+DisposableTests.swift @@ -0,0 +1,29 @@ +import MobiusCore +import Nimble +import Quick + +@available(iOS 13.0, *) +class TaskDisposableTests: QuickSpec { + override func spec() { + describe("Task+Disposable") { + var task: Task! + var disposable: Disposable! + + beforeEach { + task = Task { + try? await Task.sleep(nanoseconds: 1_000_000_000) + } + disposable = task.asDisposable + } + + it("starts off not cancelled") { + expect(task.isCancelled).to(beFalse()) + } + + it("disposable cancels the task that owns it") { + disposable.dispose() + expect(task.isCancelled).to(beTrue()) + } + } + } +}