Last active
May 7, 2024 08:13
-
-
Save KaneCheshire/b13ad47c2f8cdfef7c6225306a3ba919 to your computer and use it in GitHub Desktop.
Type-erased Swift Task that cancels itself on deinit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// A type-erased task that you can store in a collection | |
/// to allow you to cancel at a later date. | |
/// | |
/// Upon deinit of the task, the task will be cancelled | |
/// automatically. Similar to Combine's AnyCancellable. | |
final class AnyTask { | |
/// Call this cancellation block to cancel the task manually. | |
let cancel: () -> Void | |
/// Checks whether the task is cancelled. | |
var isCancelled: Bool { isCancelledBlock() } | |
private let isCancelledBlock: () -> Bool | |
deinit { | |
// On deinit, if the task is not cancelled then cancel it | |
if !isCancelled { cancel() } | |
} | |
/// Constructs an AnyTask from the provided Task. | |
/// The provided task is held strongly until AnyTask is | |
/// deinitted. | |
/// - Parameter task: The task to construct with. | |
init<S, E>(_ task: Task<S, E>) { | |
cancel = task.cancel | |
isCancelledBlock = { task.isCancelled } | |
} | |
} | |
extension Task { | |
var eraseToAnyTask: AnyTask { .init(self) } | |
} | |
extension Array where Element == Task<Void, Never> { | |
var erased: [AnyTask] { map(\.eraseToAnyTask) } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That’s nice! But means there’s a dependency on Combine which is a system library and not a language library right?