3
votes

Right now I have some older code I wrote years ago that allows an iOS app to queue up jobs (sending messages or submitting data to a back-end server, etc...) when the user is offline. When the user comes back online the tasks are run. If the app goes into the background or is terminated the queue is serialized and then loaded back when the app is launched again. I've subclassed NSOperationQueue and my jobs are subclasses of NSOperation. This gives me the flexibility of having a data structure provided for me that I can subclass directly (the operation queue) and by subclassing NSOperation I can easily requeue if my task fails (server is down, etc...).

I will very likely leave this as it is, because if it's not broke don't fix it, right? Also these are very lightweight operations and I don't expect in the current app I'm working on for there to be very many tasks queued at any given time. However I know there is some extra overhead with using NSOperation rather than using GCD directly.

I don't believe I could subclass a dispatch queue the way I can an NSOperationQueue, so there would be extra code overheard for me to maintain my own data structure and load this into & out of a dispatch queue each time the app is sent to the background, right? Also not sure how I'd handle requeueing the job if it fails. Right now if I get a HTTP 500 response from the server, for example, in my operation code I send a notification with a deep copy of the failed NSOperation object. My custom operation queue picks this notification up and adds the task to itself. Not sure how of if I'd be able to do something similar with GCD. I would also need an easy way to cancel all operations or suspend the queue when network connectivity is lost then reactivate when network access is regained.

Just hoping to get some thoughts, opinions and ideas from others who might have done something similar or are more familiar with GCD than I am.

Also worth noting I know there's some new background task support coming in iOS 7 but it will likely be a while before that will be my deployment target. I am also not sure yet if it would exactly do what I need, so at the moment just looking at the possibility of GCD.

Thanks.

1
While I am sure it can be done, here are a few thoughts off the top of my head. 1. GCD does not have built-in support for cancellation; you will have to roll your own. 2. No easy subclassing like NSOperationQueue so you will have to maintain a list of operations separately instead of in your subclass and this may be a future source of errors. 3. NSOperationQueue uses GCD internally as of iOS 4+. 4. Why re-write something that isn't broken?Robotic Cat
Yep, your point 4 is exactly what I said myself. And yes, NSOperationQueue uses GCD under the covers. I also know it's easiest to work with the highest level of abstraction, but with some overhead. I'm not trying to solve a problem I'm not having - i.e. I'm not seeing performance problems around this - but rather just checking since this is older code if it made sense to update and if there was something I was missing in my more limited experience with GCD that would make it easier to refactor than it was seeming it would be. Will likely leave as it is. Thanks.fogwolf

1 Answers

1
votes

If NSOperation vs submitting blocks to GCD ever shows up as measurable overhead, the problem isn't that you're using NSOperation, it's that your operations are far too granular. I would expect this overhead to be effectively unmeasurable in any real-world situation. (Sure, you could contrive a test harness to measure the overhead, but only by making operations that did effectively nothing.)

Use the highest level of abstraction that gets the job done. Move down only when hard data tells you that you should.