Why not keep the Swift 3 convention with lowercase letters for the enum, and then use the capitalised property on rawValue within the keyPath computed variable?
hi Rakesh: if you don’t override what it means for the operation to be finished, the system will think it’s finished right away, but it’s really still executing, or maybe waiting its turn.
this matters if you’re making another operation dependent on it — you want the async operation to really finish before starting the dependent operation.
It means If I run a nsoperation and It is using some resources then It will not be available for the other nsoperation to used while Ist operation is executing ???
In Demo I read this “For synchronous tasks, you can create an Operation subclass by overriding the main() method.” So If I am calling webservices using NSUrlSession in Operation Queue by Overriding main function.So Is It wrong ??
URLSession tasks are asynchronous. If you want to use them in an OperationQueue, you should subclass AsyncOperation and override main as described in this video.
In video 7, when you set the state property, why should we call the didChangeValueForKey twice in willSet and didSet methods ? Is it not enough if we just call it once in each function ?
hi Preetham: it’s actually willChange in willSet and didChange in didSet, but it’s one of those Apple Mysteries that I just take on faith. Apple’s KVO documentation says to write both for manual notification. In this case, we’re notifying the Operations scheduler, which might pay attention to one set or the other, or to both, for different purposes.
I noticed tsan complaining about setting the state as a race condition.
I think the solution is to not set the state after main() but to actually override main(), check if it’s cancelled, then set the state. Then in the subclass, go ahead and call super.main() and go about your normal async call.
override open func start() {
if isCancelled {
state = .finished
return
}
main()
}
override open func main() {
if self.isCancelled { return }
self.state = .executing
}
Nope. Still seeing race conditions…
Seems to be centered around cancel. These are for UITableView cells bg images, so it’s as prefetch cancels them. I also cancel them when doing a beginUpdates as the IndexPath changes. Although I think I will modify the downloadsInProgress to be indexed by the ObjectID instead of the cell index.
So, I think the issue was an oversight on my part. I was not removing the Operation from the downloadsInProgress list using the completionBlock of the Operation. I think that was causing the issues.
So I think the issue might be the return thread of the URLSession:dataTask is not the same thread as the Operation.
So what I did was grab the current OperationQueue, then grab it’s underlyingQueue and then async back to it to set the Operation data.
override func main() {
super.main()
let queue = OperationQueue.current
if let url = URL(string: path) {
let request = NSMutableURLRequest(url: url)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
DataManager.shared.removeActivity()
if let thread = queue?.underlyingQueue {
thread.async {
print("^ I'm back on the current queue!")
self.data = data
self.response = response
self.error = error
self.state = .finished
}
} else {
print("^ I couldn't figure out the current queue")
self.data = data
self.response = response
self.error = error
self.state = .finished
}
}
if self.isCancelled { return }
DataManager.shared.addActivity()
task.resume()
} else {
self.state = .finished
}
}