ios - Executing the NSOperation when all other operations in NSOperationQueue finished no matter whether they finished successfully or not -
hi have strange situation here :
overview:
i working on app user can initiate multiple operations , these operations run on background thread hence not block ui. of these operations dependent on each other , not. in order ensure operation execute after necessary dependencies operations finished executing using dependency property of operation. making use of asynchronous operations.
here implementation :
import uikit import coredata import swiftyjson class vmbaseoperation: nsoperation { 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 } 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.executing = false self.finished = false } }
what :
each operation takes web request , attempts data server , if fails, tries 3 times before setting finished status false calling operationfailed
method , there stopping dependent operation executing forever.on other hand if succeeds changes finished status true calling operationcompleted
hence triggers execution of remaining dependent operations.
what issue:
dependency works charm. no issue that. need sync data server when operations in operation queue finished executing no matter whether finished or not.
easiest way create operation sync data server , add dependent operation operations added operationqueue.
but because of above mentioned nature of operation, if 1 operation fails stops execution of dependent operations (as expected) because sync data server operation dependent operation never execute if 1 operation fails :(
what need :
while maintaining dependency mentioned above need know how execute operation sync data server when operations in operation queue finishes executing no matter whether succeed or fail.
is possible :( please me out . in advance.
with implementation operationfailed
:
func operationfailed(){ self.executing = false self.finished = false }
you break nsoperation's native logic:
operation dependencies
dependencies convenient way execute operations in specific order. can add , remove dependencies operation using adddependency: , removedependency: methods. default, operation object has dependencies not considered ready until of dependent operation objects have finished executing. once last dependent operation finishes, however, operation object becomes ready , able execute.
the dependencies supported nsoperation make no distinction whether dependent operation finished or unsuccessfully. (in other words, canceling operation marks finished.) it determine whether operation with dependencies should proceed in cases dependent operations were cancelled or did not complete task successfully. may require incorporate additional error tracking capabilities operation objects.
by design if operation fails should finish. mark somehow (some special property or cancelled
one).
dependent operations should check possible start. following should job:
var requiredependencescompletion: bool = true override var ready: bool { if requiredependencescompletion { op in self.dependencies { if op.cancelled { cancel() } } super.ready }
here override ready
property determine should done. if requiredependencescompletion
true
operation check dependences , cancel if 1 of them cancelled.
set requiredependencescompletion
true
typical operations , false
barrier operation start in case.
Comments
Post a Comment