Bolts framework task queue - ios

I'm developing an iOS app and have been looking into using Bolts framework by Parse (facebook) to manage network operations (using Alamofire for network requests).
I'm wondering if there is a good implementation/pattern out there for a task queue for Bolts. I need to have offline functionality and therefore I (think) need to have some sort of task queue so if the user is offline all of their save/create operations are saved (queued and persisted) and then executed once they have a network connection, also needed for retries of requests. I've looked at NSOperation queue so I may go that route although I like how Bolts does things with BFTask and would prefer to use that.

I understand your problem, but I think that you mix up the purpose of NSOperation queue and BFTasks a little bit.
BFTasks are used in order to use and create asynchronous and synchronous methods/network requests in a cohesive and minimalistic way. For instance, suppose that would have to login a user, present a search view and then download user`s search query results.
In order to keep your app optimized and have the UI at 60fps you would need to run your network request asynchronously. Apparently, you would present search view only if user logged in (using your method) (this technique is called "async tasks in series") and then you would download search results using parallel async requests (Think about downloading movie artworks for a movie name query in iTunes. They start downloading at the same time, "in parallel" to each other, so user images are downloaded independently from each other). (Whereas this is one is called "async tasks in parallel").
As you can see from this example, we can only achieve the desired logic along with desired performance if we use sequential and parallel async requests.
Bolts framework allows you to achieve all of the aforementioned logic in a VERY cohesive and convenient way.
NSOperation queue, on the other hand, allow you to build a complex sequence of both sync and async methods. It even allows you to get the status of a particular operation and bind dependencies. A good example of it, is view controller lifecycle.
If I were you, I would first learn how to use Bolts and NSOperation queue apart from each other. Then, depending on what you actually need to achieve in your app in terms of functionality, I would start thinking about binding Bolts and NSOperation queue in a class or a struct (in case you use swift). Like using Bolts for "online" stuff (executing network requests) and NSOperation queue for "offline" (storing the sequence of actions the user makes while being offline, in order to execute this sequence when the internet connection is back).
You can read more about NSOperation here and about Bolts for iOS here.
UPDATE:
In terms of implementation pattern, one suggestion that you might want to consider is to create a simple class/struct that would be responsible for storing("stacking") your Bolts methods. You can use arrays for sequential logic and sets for parallel one. You can also use sets to easily make sure that some of the requests happen only once as sets store only unique objects. Honestly, in my opinion, you should try to implement something similar to what I described, because Bolts itself (almost for sure) incorporates NSOperation and NSOperaitionQueue.
By the way, since Parse iOS SDK is open source right now, you could see how they implement saveEvenutually method which saves an object when internet connection is back and think how you could replicate their logic according to your needs.

Related

Best way to ensure an initial network request is completed before other requests are sent (iOS app)

An app I am working on requires creating a container object on a server and inserting items into that container. I don't want to create the container object until the first item needs to be inserted. However, creating the container object requires some initialization that may take a little time. While that container is still initializing the user can still to send insertion requests that aren't getting handled because the container isn't ready yet. I have two main questions:
Should this be dealt with on the client or server side?
What is the best practice for dealing with kind of this issue?
Essentially, I need to ensure my initial createContainer data task in complete before any insertItem requests are sent.
Addition Information
An insertItem request is sent by clicking on a corresponding tableViewCell. The first tableViewCell a user clicks on sends a createContainer request that creates a container holding the first item.
For a container holding n items, the request should be sent in the following order:
createContainer(Container(with: item1)
insertItem(item2)
...
insertItem(itemn)
After the first request completes, the remaining n – 1 requests may complete in any order.
My Thoughts
It sounds like I want the createContainer request to be handled synchronously while the insertItem request should be handled asynchronously. I'm not sure if that is the best approach or even how to perform that appropriately, so any guidance would be greatly appreciated.
You can use a NSOperationQueue and multiple NSOperations to implement your desired behavior. A NSOperation instance can be dependent on the completion of another NSOperation instance:
dependencies
An array of the operation objects that must finish
executing before the current object can begin executing.
For your example this would mean that the insertItem-Operations are dependent on the createContainer operation.
When you add all those operations to a NSOperationQueue your createContainer operation will run first. When it has finished, the other operations will start running as their dependencies are now satisfied. You can also control how many operations you want to run concurrently using maxConcurrentOperationCount on NSOperationQueue.
As you will be using asynchronous API in your NSOperations you will need to implement a ConcurrentOperation and handle the state changes yourself. The API Reference is explaining this in pretty good detail.
Check out the API Reference for NSOperation for further information.
There is also a nice NSHipster article on NSOperations.
Adding to the NSOperationQueue answer, it's sometimes difficult to manually manage all the state changes that an NSOperation requires to handle something asynchronous like a network call.
To simplify that, you can use a Swift Library called Overdrive. It's an amazing library in which you simply subclass a Task class and write your network code in the run() function. And when you're done, you simply call self.finish to finish the task. Here's an example: Just create a simple download task:
Then, just add it to the queue.
You can also add dependencies between tasks, which basically solves your use case.
Hope this helps.

Async NSURLConnection triggering other Async NSURLConnection: what is the best way of doing this?

this is an open question aiming at understanding what is the best practice or the most common solution for a problem that I think might be common.
Let's say I have a list of URLs to download; the list is itself hosted on a server, so I start a NSURLConnection that downloads it. The code in connectionDidFinishLoading will use the list of URLs to instantiate one new NSURLConnection, asynchronously, per each URL; this in turn will trigger even more NSURLConnections, and so on - until there are no more URLs. See it as a tree of connections.
What is the best way to detect when all connections have finished?
I'm aiming the question to iOS7, but comments about other versions are welcome.
A couple of thoughts:
In terms of triggering the subsequent downloads after you retrieve the list from the server, just put the logic to perform those subsequent downloads inside the completion handler block (or completion delegate method) of the first request.
In terms of downloading a bunch of files, if targeting iOS 7 and later, you might consider using NSURLSession instead of NSURLConnection.
First, the downloading of files with a nice modest memory footprint is enabled by initiating "download" tasks (rather than "data" tasks).
Second, you can do the downloads using a background NSURLSessionConfiguration, which will let the downloads continue even if the user leaves the app. See the Downloading Content in the Background section of the App Programming Guide for iOS. There are a lot of i's that need dotting and t's that need crossing if you do this, but it's a great feature to consider implementing.
See WWDC 2013 What's New in Foundation Networking for an introduction to NSURLSession. Or see the relevent chapter of the URL Loading System Programming Guide.
In terms of keeping track of whether you're done, as Wain suggests, you can just keep track of the number of requests issued and the number of requests completed/failed, and in your "task completion" logic, just compare these two numbers, and initiate the "all done" logic if the number of completions matches the number of requests. There are a bunch of ways of doing this, somewhat dependent upon the details of your implementation, but hopefully this illustrates the basic idea.
Instead of using GCD you should consider using NSOperationQueue. You should also limit the number of concurrent operations, certainly on mobile devices, to perhaps 4 so you don't flood the network with requests.
Now, the number of operations on the queue is the remaining count. You can add a block to the end of each operation to check the queue count and execute any completion logic.
As Rob says in his answer you might want to consider NSURLSession rather than doing this yourself. It has a number of advantages.
Other options are building your own download manager class, or using a ready-made third party framework like AFNetworking. I've only worked with AFNetworking a little bit but from what I've seen its elegant, powerful, and easy to use.
Our company wrote an async download manager class based on NSURLConnection for a project that predates both AFNetworking and NSURLSession. It's not that hard, but it isn't as flexible as either NSURLSession or AFNetworking.

Using GCD for offline persistent queue

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.
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.

Using AFNetworking to process multiple JSON responses for a single request

I'm trying to find a way to open up a connection to a web service and have that service send down JSON objects on an as-needed basis.
Say I request 20 profiles from a service. Instead of waiting for the service to build all 20, the service would build the first profile and throw it back down to the client until all 20 are created.
I've been using AFNetworking and would like to continue using it. Eventually I'd like to contribute this component back to the community if it requires an addition.
Anyone have any ideas on tackling something like this? Right now I have a service pushing JSON every few seconds to test with.
A couple of thoughts:
If you want to open a connection and respond to transmissions from the server, socket-based model seems to make sense. See Ray Wenderlich's How To Create A Socket Based iPhone App and Server for an example (the server-side stuff is likely to change based upon your server architecture, but it gives you an example). But AFNetworking is built on a NSURLConnection framework, not a socket framework, so if you wanted to integrate your socket classes into that framework, a non-inconsiderable amount of work would be involved.
Another, iOS-specific model is to use Apple's push notification service (see the push-related sections of the Local and Push Notification Programming Guide).
A third approach would be to stay with a pull mechanism, but if you're looking for a way to consume multiple feeds in a non-serial fashion would be to create multiple AFURLConnectionOperation (or the appropriate subclass) operations, and submit them concurrently (you may want to constraint maxConcurrentOperations on the queue to 4 or 5 as iOS can only have so many concurrent network operations). By issuing these concurrently, you mitigate many of the delays that result from network latencies. If you pursue this approach, some care might have to be taken for thread safety, but it's probably easier than the above two techniques.
This sounds like a job for a socket (or a web socket, whatever is easier).
I don't believe there is support for this in AF. This could be implemented in the NSURLConnection's didRecieveData method. This is triggered every time a piece of data is received, so you can do your parsing and messaging from that point. Unfortunately, I can't think of a very clean way to implement this.
Perhaps a better approach to this is to handle the appropriate rerequest via a pagination-style technique. You would request page 1 of profiles with 1/page, then request page 2, etc. You could then control the flow, i.e. if you want to request all in paralel or request one then the next sequentially. This would be less work to implement, and would (in my opinion) be cleaner and easier to maintain.
AFNetworking supports batching of requests with AFHTTPClient -enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock:.
You can use this method to return on each individual operation, as well as when all of the operations in the batch have finished.

How to cleanly encapsulate and execute in sequence a series of background tasks in iOS?

My app includes a back-end server, with many transactions which must be carried out in the background. Many of these transactions require many synchronous bits of code to run.
For example, do a query, use the result to do another query, create a new back-end object, then return a reference to the new object to a view controller object in the foreground so that the UI can be updated.
A more specific scenario would be to carry out a sequence of AJAX calls in order, similar to this question, but in iOS.
This sequence of tasks is really one unified piece of work. I did not find existing facilities in iOS that allowed me to cleanly code this sequence as a "unit of work". Likewise I did not see a way to provide a consistent context for the "unit of work" that would be available across the sequence of async tasks.
I recently had to do some JavaScript and had to learn to use the Promise concept that is common in JS. I realized that I could adapt this idea to iOS and objective-C. The results are here on Github. There is documentation, code and unit tests.
A Promise should be thought of as a promise to return a result object (id) or an error object (NSError) to a block at a future time. A Promise object is created to represent the asynchronous result. The asynchronous code delivers the result to the Promise and then the Promise schedules and runs a block to handle the result or error.
If you are familiar with Promises on JS, you will recognize the iOS version immediately. If not, check out the Readme and the Reference.
I've used most of the usual suspects, and I have to say that for me, Grand Central Dispatch is the way to go.
Apple obviously care enough about it to re-write a lot of their library code to use completion blocks.
IIRC, Apple have also said that GCD is the preferred implementation for multitasking.
I also remember that some of the previous options have been re-implemented using GCD under the hood, so you're not already attached to something else, Go GCD!
BTW, I used to find writing the block signatures a real pain, but if you just hit return when the placeholder is selected, it does all that for you. What could be sweeter than that.

Resources