Last active
October 9, 2015 21:49
-
-
Save hirad/5ff9b62df1b2cb549e47 to your computer and use it in GitHub Desktop.
A simple NSOperation subclass to make creating concurrent operations easier
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
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 | |
} | |
} |
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
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