I am working on a design of an iPhone app. I have a pretty intense process to kick off, defined at a high level as follows:
- User selects item from UITableView for inApp purchase.
- User confirms purchase in UI.
- Asynchronous process goes to App Store to check to see if item has been purchased before. If not, the item is purchased. The iPhone app is then notified that the item purchase was successful. (If it was purchased previously, the app doesn't care and proceeds to step 4.)
- The app then goes to my private server to download the data for the item purchased.
- The app then imports the data into CoreData.
At each step in the process, of course, errors are reported to the user and the entire process stops.
I have a class called activityIndicatorController that presents a nice UIActivityIndicator for the user along with some text indicating what is going on. At each step in the process, the label on the activityIndicator must be updated with new status.
Question/Concern:
It seems from a design and coding standpoint, the EASIEST thing to do would be to use one big NSOperation for all steps. However, I'm concerned that this may hamstring me later on. I don't want to go down the wrong path and then have to tear out a bunch of code later.
My gut tells me it would be BETTER to implement three separate NSOperations (OpInAppPurchase, OpDownload, OpImport). However, each subsequent operation is not only dependent on the one before it, but if one fails, the rest of the NSOperations should not even be called at all. But, I'm not sure how to design/code this.
Any help is appreciated.
EDIT:
Thanks for ev开发者_JAVA技巧eryone's help so far. For what I am trying to accomplish, I do not want the user to cancel the operation. However, I DO want the app to be able to cancel subsequent operations. What I failed to realize and only just discovered by trial and error (i.e. a "duh" moment) is that when an operation is kicked off in a separate process, any child-operations that are kicked off are also performed in the same separate process.
After reading the Apple article linked to below, I discovered that for my needs right now, NSInvocationOperation does exactly what I need and saves me from having to create separate NSOperation objects for each process. It will then do a callback with an NSError object to the main thread if it fails or a different callback to the main thread when successful.
Perhaps I will have some other processes that I do want the user to be able to cancel in the future and I will use NSOperation with the other events.
By adding each step into an NSOperationQueue
You can check to ensure that step failed before continuing. See this article on the general approach.
You can also initiate and respond to cancellation requests from the NSOperation if the operation encounters a problem. See Responding to Cancellation Events in this article.
Responding to Cancellation Events:
After an operation begins executing, it continues performing its task until it is finished or until your code explicitly cancels the operation. Cancellation can occur at any time, even before an operation begins executing. Although the NSOperation class provides a way for clients to cancel an operation, recognizing the cancellation event is voluntary by necessity. If an operation were terminated outright, there might not be a way to reclaim any memory or resources that had been allocated. As a result, operation objects are expected to check for cancellation events and to exit gracefully when they occur in the middle of the operation.
Use an NSOperationQueue
. Encapsulate each task in its own NSOperation
. Set the dependencies using addDependency:
.
"How to prevent the other operations from being executed when one fails?", you ask.
Well, first, make sure your NSOperation
objects are good citizens and check regularly whether they've been cancelled so they can stop execution.
Then, just go through each operation's dependencies
to check whether those dependencies are cancelled. If they are, just quit/cancel the current operation too.
精彩评论