Skip to content

Instantly share code, notes, and snippets.

@MarcoSantarossa
Last active August 2, 2023 13:23
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save MarcoSantarossa/406652eeb00d3281980cba5fc21c5ff6 to your computer and use it in GitHub Desktop.
Save MarcoSantarossa/406652eeb00d3281980cba5fc21c5ff6 to your computer and use it in GitHub Desktop.
How to write and use an asynchronous operation
import Foundation
class AsyncOperation: Operation {
enum State: String {
case isReady, isExecuting, isFinished
}
override var isAsynchronous: Bool {
return true
}
var state = State.isReady {
willSet {
willChangeValue(forKey: state.rawValue)
willChangeValue(forKey: newValue.rawValue)
}
didSet {
didChangeValue(forKey: oldValue.rawValue)
didChangeValue(forKey: state.rawValue)
}
}
override var isExecuting: Bool {
return state == .isExecuting
}
override var isFinished: Bool {
return state == .isFinished
}
override func start() {
guard !self.isCancelled else {
state = .isFinished
return
}
state = .isExecuting
main()
}
}
final class FetchOperation: AsyncOperation {
private(set) var dataFetched: Data?
private let session = URLSession(configuration: .default)
private var dataTask: URLSessionDataTask?
override func main() {
let url = URL(string: "https://jsonplaceholder.typicode.com/users")!
dataTask = session.dataTask(with: url) { [weak self] (data, _, _) in
guard let `self` = self else { return }
// We could improve this fallback with a Result enum
guard
!self.isCancelled,
let data = data else {
self.state = .isFinished
return
}
self.dataFetched = data
self.state = .isFinished
}
dataTask?.resume()
}
}
@robwithhair
Copy link

Is this thread safe? I'm reading lots about thread safety of writing to state. I'm bit confused.

@badrinathvm
Copy link

yea facing same issue.

@MarcoSantarossa
Copy link
Author

@robwithhair/@badrinathvm so far I didn't encounter thread problems. I should investigate about this issue.

@MarcoSantarossa
Copy link
Author

Looking around, I think we could use an internal GCD queue to update the state with a sync work. I will update this code asap.

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