ios - Interdependent NSURLSession tasks with NSOperation and NSOperationQueue (Swift) -


problem: develop ios app in swift perfoming initial load right after login. sequence (of rest based calls via nsurlsession) this:

  1. login user account -> asynchronous response returns userid
  2. get countries userid -> asynchronous response returns countryid's
  3. get products countryid -> ...etc...

basically find elegant way on how implement such sequence.

approach: first started calling new (dependent) rest call in completion handler of another. if many calls need executed , dependency levels more one's described above code looks little bit messy...

i came accross wwdc 2015 session on nsoperations , thought might idea can define dependencies easy. unfortunately sample code provided apple not give answer problem described above...is (and did not it?)? while playing around operations not make mind on how solve initialization problem @ time creating different operations (loginoperation, countryoperation (dependent on loginoperation), productoperation (dependent on countryoperation), etc..)

i found these posts helpful, stil i'm lacking of understanding how approch best problem described: how download multiple files sequentially using nsurlsession downloadtask in swift chaining nsoperation : pass result operation next one nsurlsession nsblockoperation , queues

difficulties: initializing operation b @ time when operation finished , has returned result going used operation b.

if still relevant, may have answer.

the problem here you’re trying defer initialization until first operation finished. that’s dead end. operations meant created early, , order guaranteed using dependencies.

so let’s discuss approaches extremely frequent problem.

(you can note examples written in wwdc-session style. because use operations library based on talk. take @ if you’re interested in operations-based architecture.)

1. use external mutable shared state (cocoa-way)

that means that, example, have usercontroller, instance of you’re passing both loginoperation , countryoperation. loginoperation writes userid controller, , countryoperation reads that:

class usercontroller {     var userid: string? }  class loginoperation: operation {      let usercontroller: usercontroller      init(usercontroller: usercontroller) {         self.usercontroller = usercontroller     }      override func execute() {         // networking stuff         usercontroller.userid = receiveduserid         finish()     }  }  class countryoperation: operation {      let usercontroller: usercontroller      init(usercontroller: usercontroller) {         self.usercontroller = usercontroller     }      override func execute() {         let userid = usercontroller.userid         // continue     }  } 

and then:

let queue = operationqueue() let usercontroller = usercontroller() let login = loginoperation(usercontroller: usercontroller) let country = countryoperation(usercontroller: usercontroller) country.adddependency(login) queue.addoperation(login) queue.addoperation(country) 

the problem solution it’s pretty complex , incredibly hard test. , swift doesn’t mutable shared state much.

2. initialize operations functions instead of values (swifty-way)

well, not obvious amazingly elegant solution. saw, values copied on initialization time. need retrieve needed value on execution time (as previous example), without such tight coupling. well, can done - pass function initializer!

class loginoperation: operation {      private(set) var userid: string?      override func execute() {         // networking stuff         let receiveduserid = "1"         userid = receiveduserid         finish()     }  }  class countryoperation: operation {      private let getuserid: () -> string      init(getuserid: () -> string) {         self.getuserid = getuserid     }      override func execute() {         /* because operation depends on `loginoperation`,         `getuserid()` called after `loginoperation` finished. */         let userid = self.getuserid()         // continue     }  } 

and then:

let queue = operationqueue() let login = loginoperation() // force-unwrap no good, of course, example it's ok let country = countryoperation(getuserid: { login.userid! }) country.adddependency(login) queue.addoperation(login) queue.addoperation(country) 

as see, no tight coupling, no shared mutable state (countryoperation can read, not write — good). , it’s ridiculously easy test: pass whatever want countryoperation initializer, don’t need loginoperation @ test it!

with approach, actually, main goal of nsoperation achieved: distinctive, abstract pieces of work. countryoperation doesn’t know loginoperation, nor other shared instance.

i use approach lot in projects , works amazingly.

please reply if have further questions :)


Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

How to get the ip address of VM and use it to configure SSH connection dynamically in Ansible -

javascript - Get parameter of GET request -