Skip to content

Instantly share code, notes, and snippets.

@voncannon
Last active March 14, 2024 19:36
Show Gist options
  • Save voncannon/7fa4db1463270e9dfa996617b1ece5e4 to your computer and use it in GitHub Desktop.
Save voncannon/7fa4db1463270e9dfa996617b1ece5e4 to your computer and use it in GitHub Desktop.
Swift Async Operation
//
// AsyncOperation.swift
// TopoLock
//
// Created by VonCannon Tech, Inc. on 8/13/23.
//
import Foundation
//Originally taken fromm: https://gist.github.com/Sorix/57bc3295dc001434fe08acbb053ed2bc
class AsyncOperation: Operation {
public override var isAsynchronous: Bool {
return true
}
public override var isExecuting: Bool {
return state == .executing
}
public override var isFinished: Bool {
return state == .finished
}
public override func start() {
if self.isCancelled {
state = .finished
} else {
state = .ready
main()
}
}
open override func main() {
if self.isCancelled {
state = .finished
} else {
state = .executing
}
}
public func finish() {
state = .finished
}
// MARK: - State management
public enum State: String {
case ready = "Ready"
case executing = "Executing"
case finished = "Finished"
fileprivate var keyPath: String { return "is" + self.rawValue }
}
/// Thread-safe computed state value
public var state: State {
get {
stateQueue.sync {
return stateStore
}
}
set {
let oldValue = state
willChangeValue(forKey: state.keyPath)
willChangeValue(forKey: newValue.keyPath)
stateQueue.sync(flags: .barrier) {
stateStore = newValue
}
didChangeValue(forKey: state.keyPath)
didChangeValue(forKey: oldValue.keyPath)
}
}
private let stateQueue = DispatchQueue(label: "AsynchronousOperation State Queue", attributes: .concurrent)
/// Non thread-safe state storage, use only with locks
private var stateStore: State = .ready
}
//
// TestAsyncOperation.swift
// TopoLock
//
// Created by bvc on 8/14/23.
//
import Foundation
class TestAsyncOperation: AsyncOperation {
override func main() {
super.main()
Task {
guard !self.isCancelled else {
return
}
await woot()
self.finish()
}
}
}
func woot() async {
//
}
@voncannon
Copy link
Author

I really wish apple would update Operations to take async/await by default so we don't have to the KVO dance.

@voncannon
Copy link
Author

A possible alternative that jrendel told me about: https://stackoverflow.com/a/73072799

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment