3

Lets say we have NSOperation A and NSOperation B. B is dependant on A finishing and performing some setup as a result of A.completionBlock being called and finished. This means that B.addDependency(A) cannot be used as B cannot be constructed until A has finished. Therefore we opt to use A.waitUntilFinished() on a separate thread before constructing and starting B.

However, because the completionBlock of A is called on a different thread, the thread that we call A.waitUntilFinished() unblocks before A.completionBlock has finished executing and hence on construction of B the necessary prerequisites have not been completed.

Because the apple NSOperation API does not provide any control over where A.completionBlock is dispatched, what is the usual way to handle this issue?

Edit:

The option I've tried so far is to wrap NSOperation B in an NSBlockOperation C and then call C.addDependency(A) so that B isn't constructed until A is finished. However this still doesn't solve the problem as asynchronous start must still be called within NSBlockOperation C and the completion block still flies off to another thread.

Michael
  • 2,218
  • 1
  • 22
  • 31
  • Is it the case that some of your code in A.completionBlock should actually be going in NSOperation A itself? – occulus Nov 05 '13 at 12:17
  • can you just call B.start at the end of A.completionBlock? – lead_the_zeppelin Nov 05 '13 at 12:17
  • NSOperation A saves Model 1 to a relational database which then returns a unique identifier for that model. Model 1 is related to Model 2 which is saved by NSOperation B. B needs to send the unique identifier of Model 1 to the database to form this relation. Placing code from `A.completionBlock` in A would be coupling two APIs that shouldn't really be coupled. Calling `B.start()` from `A.completionBlock` isn't an option either, as the `save()` method of the models are independent of each other. – Michael Nov 05 '13 at 12:33
  • 2
    See http://stackoverflow.com/questions/18745635/when-will-completionblock-be-called-for-dependencies-in-nsoperation – Rob Nov 05 '13 at 12:52
  • @Michael, now I understand what you was looking for when you wrote wrote your comments in my topic about NSOperation internals. My topic is really not related to yours. Could you please update your question with a code (pseudocode or shortened variant maybe) so it would be possible to understand how you try to pass your unique indentifier from `Operation1's completionBlock` to `Operation2`? – Stanislav Pankevich Nov 05 '13 at 21:48
  • Do I understand right, that you question could be rephrased like this: how a data we've got upon completion of Operation1 (your "unique identifier") could be passed to Operation2, that has the Operation1 as its dependency? – Stanislav Pankevich Nov 05 '13 at 21:49
  • Hi Stanislaw - it can indeed be rephrased like that. – Michael Nov 07 '13 at 12:00
  • The relation of your topic to mine was that I was attempting to understand the NSOperation internals (specifically the invocation of completionBlock) by the internal KVO method that I noticed in the call stack in the same way you did. – Michael Nov 07 '13 at 12:00
  • I have ended up implementing the Promise pattern in a similar fashion to what was described in the thread that Rob posted. – Michael Nov 07 '13 at 12:01

1 Answers1

0

Since what you want to happen is to have Model 2 save once Model 1's uuid is known, can you express it in those terms, and have Model 2 observe the uuid of Model 1 (or use a notification) and initiate operation B once it has a value set?

Airsource Ltd
  • 31,830
  • 13
  • 70
  • 75