Hi I have a strange situation here :
OverView:
I am working on an app where user can initiate multiple operations and all these operations w
Never mind I figured it out :)
Setting the finished status to true and false triggers the KVO of NSOperationQueue and hence either starts or cancels the operation of dependent operations.
If I want my operation to execute at any point whether the dependency operations finished successfully or not I can't make use of finished flag. In this case finished flag should always be true to indicate operation finished its execution.
But how will I ensure the management of decency chain for those operations that have dependencies set and really depends whether the previous operation was successful or not ?? Simple I added another variable called finishedSuccessfully to my NSOperationSubclass.
When a operation fails though it sets the finished flag to true it will set finishedSuccessfully to false. This will cause the dependent operations start method to get called.
In the start method of dependent operation, it will iterate over all the dependency operations and checks has all of them finished with finishedSuccessfully = true.
If yes that means all the dependency operations have finished execution and finished it successfully so it can start execution. On the other hand if any one of them has finishedSuccessfully = false, that means operation finished executing but failed to do whatever it was supposed to do hence this operation should also stop itself and inform its dependents that it finished with finishedSuccessfully = false.
Summary :
Operations will execute only after the execution of all the dependency operations finished executing no matter whether they finished successfully or not.
Operations which are actually concerned about the execution status of their dependency operations will check for the status and then finally decides whether to continue execution or not.
Dependency chain is maintained as well as the confirmation that sync operation executes as well :)
Here is my implementation :
import UIKit
import CoreData
import SwiftyJSON
class VMBaseOperation: NSOperation {
var finishedSuccessfully : Bool = false
var finishedStatus : Bool = false
var executionStatus : Bool = false
var retryCount : Int = 0
private (set) var requestToQueue : BaseRequest? = nil
var vmOperationCompletionBlock: ((JSON?) -> Void)?
var vmOperationFailureBlock: ((WebResponseError?) -> Void)?
override init() {
super.init()
}
convenience init(withVMRequest request : BaseRequest) {
self.init()
requestToQueue = request
}
override func start() {
if self.cancelled {
self.finished = true
return
}
//those operations which actually wants to know if all its dependency operations finished successfully or not can create a subclass of this class override start method and add the below code
for operation in self.dependencies {
if (operation as! VMBaseOperation).finishedSuccessfully == false {
self.operationFailed()
return
}
}
//others can ignore.
NSThread.detachNewThreadSelector(#selector(main), toTarget: self, withObject: nil)
self.executionStatus = true
}
override func main() {
if self.cancelled {
return
}
self.hitWebService()
}
func hitWebService(){
let webserviceManager = WebServiceManager()
webserviceManager.getResponseFromRequest(requestToQueue!) { (requset, response, data, error) in
let error = WebResponseError.checkResponse(response, request: requset, error: error)
if error != nil {
if error == WebResponseError.NO_INTERNET {
if self.vmOperationFailureBlock != nil {
self.vmOperationFailureBlock!(error)
}
self.operationFailed()
}
else{
self.retryCount += 1
if self.retryCount == 3 {
if self.vmOperationFailureBlock != nil {
self.vmOperationFailureBlock!(error)
}
self.operationFailed()
}
else{
self.hitWebService()
}
}
}
else{
if data == nil {
self.retryCount += 1
if self.retryCount == 3 {
if self.vmOperationFailureBlock != nil {
self.vmOperationFailureBlock!(nil)
}
self.operationFailed()
}
else{
self.hitWebService()
}
}
else{
let json = JSON(data: data!)
if self.vmOperationCompletionBlock != nil {
self.vmOperationCompletionBlock!(json)
}
self.operationCompleted()
}
}
}
}
override var finished: Bool {
get{
return finishedStatus
}
set{
self.willChangeValueForKey("isFinished")
finishedStatus = newValue
self.didChangeValueForKey("isFinished")
}
}
override var executing: Bool {
get{
return executionStatus
}
set{
self.willChangeValueForKey("isExecuting")
executionStatus = newValue
self.didChangeValueForKey("isExecuting")
}
}
override var asynchronous: Bool{
get{
return true
}
set{
self.willChangeValueForKey("isAsynchronous")
self.asynchronous = true
self.didChangeValueForKey("isAsynchronous")
}
}
func operationCompleted(){
self.executing = false
self.finished = true
}
func operationFailed(){
self.finishedSuccessfully = false
self.operationCompleted()
}
func operationSucceeded(){
self.finishedSuccessfully = true
self.operationCompleted()
}
}