Skip to content

Instantly share code, notes, and snippets.

@hirad
Last active October 9, 2015 21:49
Show Gist options
  • Save hirad/5ff9b62df1b2cb549e47 to your computer and use it in GitHub Desktop.
Save hirad/5ff9b62df1b2cb549e47 to your computer and use it in GitHub Desktop.
A simple NSOperation subclass to make creating concurrent operations easier
public class AsyncOperation: NSOperation {
enum State {
case Pending
case Executing
case Finished
case Cancelled
var keyValueCodingKeys: [String] {
switch self {
case .Executing:
return ["isExecuting"]
case .Finished:
return ["isFinished"]
case .Cancelled:
return ["isCancelled"]
default:
return []
}
}
}
private let lock = NSRecursiveLock()
private var _state: State = .Pending {
willSet(newState) {
let allKeys = _state.keyValueCodingKeys + newState.keyValueCodingKeys
allKeys.forEach { self.willChangeValueForKey($0) }
}
didSet {
let allKeys = _state.keyValueCodingKeys + oldValue.keyValueCodingKeys
allKeys.forEach { self.didChangeValueForKey($0) }
}
}
var state: State {
get {
return _state
}
set {
self.lock { self._state = newValue }
}
}
private func lock(task: () -> () ) {
self.lock.lock()
task()
self.lock.unlock()
}
// MARK: NSOperation Subclassing
override public func cancel() {
state = .Cancelled
}
public override var cancelled: Bool {
return state == .Cancelled
}
public override var executing: Bool {
return state == .Executing
}
public override var finished: Bool {
return state == .Finished
}
public override var asynchronous: Bool {
return true
}
}
struct MockedAPI {
func makeAPICall(completion: (Int -> ())) {
let randomWait = UInt64(arc4random_uniform(10))
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(randomWait * NSEC_PER_SEC)), dispatch_get_main_queue()) {
completion(Int(randomWait) + 5)
}
}
}
class Operation: AsyncOperation {
let api = MockedAPI()
private(set) var rand: Int? = nil
var identifier: String = "AsyncOperation"
override func start() {
if self.cancelled {
return
}
self.state = .Executing
api.makeAPICall { randomNumber in
if self.cancelled {
return
}
self.rand = randomNumber
self.state = .Finished
}
}
}
extension Operation {
override var description: String {
return "\(self.identifier)"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment