Concurrent task in AFNetworking - ios

Currently I am running 3 task concurrently using AFNetworking.But my problem is that I need to refresh tableview once all the above three task complete.But as in AFNetworking all the operation are async. So any operation can finish first. I am not getting a point where I need to refresh my tableview. I am planning to do some critical section type implementation.Is there can other way to accomplish the above.

Use the built-in batched request operation feature of AFNetworking. The completion handler for the batch would include the logic to refresh your data source once all of the operations have finished.

Maybe having some sort of 'active requests array' is a solution for you.
Every time you make a request, add it to the (mutable) array.
When the request finishes, remove it from the array.
Every time a request finishes, check the array length (count).
If your array has become empty again, all request have been finished and you can reload your tableview.

Related

Should I use operation queue for this complete scenario?

I need to perform a scenario with the following steps:
To make a network call with some search parameters provided by the user
Then, to parse its JSON response and create model entities
Then, for each entity created and if it has an associated image URL, to call the corresponding service for downloading such image and to show it in a UICollectionView when download finishes.
I need to handle concurrent network calls when downloading the N images I'd need. User should have the possibility to cancel the current search flow and start a new one. In addition, I should take into account that the cell for a certain image has not been displayed yet or it has been dequeued. So, my question is: which would be the best approach for this?
Perform the first network call (no concurrency) and the JSON response parsing directly using URLSession and URLSessionDownloadTask, and using Operation and OperationQueue for the subsequent steps. Use both invalidateAndCancel() for the URLSession and cancelAllOperations() for the OperationQueue if the user wants to cancel the current search.
Perform the complete process using Operation and OperationQueue.
Any other and more appropriate approach?
The best approach would be to do either a sync or async call to make the first service call. Once completed, parse the json synchronously and then use lazy loading concept (async call) to load if any images are to be downloaded to display the images.
Perform the network call then make the model objects. return these to your VC through your API completion block.
Then reload your collection view and pass the url to each cell and have each cell worry about itself, use something like SDWebImage to show the images async in the cells..

How much time does Realm take for a write transaction to perform an Object add?

I have a collection view with Realm datasource. If I add or update an Realm Object in a write transaction then immediately try to refetch from the datasource, of course the new write is not finished. Thus what I'm doing currently is adding a 0.1 second delay before refetching.
My question is, are there better approaches? If not, how much time (magnitude of 0.0001 sec or 0.01 sec etc) does a normal Realm write > add transaction take?
Thanks!
If you're not seeing the updates to a Realm file straight away, you can call refresh on the RLMRealm / Realm object to manually force a refresh.
Normally changes are updated across all Realm objects on all threads on the next iteration of the run loop (Which you would also achieve by introducing a time delay like you have above!), but calling refresh will cause that version of the Realm object to update before the current iteration of the run loop has completed.

Multiple objects waiting for the same API response

I have an API code, which loads a data necessary for my application.
It's as simple as:
- (void) getDataForKey:(NSString*) key onSuccess:(id (^)())completionBlock
I cache data returned from server, so next calls of that functions should not do network request, until there is some data missing for given key, then I need to load it again from server side.
Everything was okey as long as I had one request per screen, but right now I have a case where I need to do that for every cell on one screen.
Problem is my caching doesn't work because before the response comes in from the first one, 5-6 more are created at the same time.
What could be a solution here to not create multiple network request and make other calls waiting for the first one ?
You can try to make a RequestManager class. Use dictionary to cache the requesting request.
If the next request is the same type as first one, don't make a new request but return the first one. If you choose this solution, you need to manager a completionBlock list then you will be able to send result to all requesters.
If the next request is the same type as first one, waiting in another thread until the first one done. Then make a new request, you API will read cache automatically. Your must make sure your codes are thread-safe.
Or you can use operation queues to do this. Some documents:
Apple: Operation Queues
Soheil Azarpour: How To Use NSOperations and NSOperationQueues
May be there will be so many time consuming solutions for this. I have a trick. Create a BOOL in AppDelegate, its default is FALSE. When you receive first response, then set it TRUE. So when you go to other screen and before making request just check value of your BOOL variable in if condition. If its TRUE means response received so go for it otherwise in else don't do anything.

Adding a "Final" NSOperation to a Queue with Undetermined Number of Operations

I'm using AFNetworking as my network stack to communicate with a web service and populate a local data store. During synchronization runs, I have an array of API endpoints to run through, and when that run is complete, I add a final operation, which takes the resulting JSON to fill up the database.
The problem I'm having is that the result of some of those JSON-fetching operations requires me to call other endpoints, and now I don't know when I should add that "Final" operation.
The way I have things working now, I have a series of primary operations, and then add the "final" operation. During that time, the primaries have returned and caused me to create secondary operations, like so:
* Primary Fetch Operation A
* Primary Fetch Operation B
* Final Operation
* Secondary Fetch Operation B1
I need to figure out how to ensure that "Final Operation" is always going to run last.
One thing I've tried is adding an observer to the operation queue's operationCount property, but it seems that it can run down to 0 before a secondary operation is added.
Unfortunately I believe the observer won't work, AFNetworking invokes callbacks from the completionBlock of NSOperation and this means that the operation is already finished and removed from the queue, which explains why you have reached a operationCount of 0 before submit the secondary operation.
You could use a dispatch_group_t to accomplish this, before scheduling an operation (primary or secondary) you enter the group (dispatch_group_enter) and then when the operation completes you leave the group (dispatch_group_leave). If the finished operation requires a secondary operation before leaving the group follow the same pattern, enter the group again and schedule the secondary operation. Finally you will be notified (dispatch_group_notify) when all the operations have completed making the perfect time to schedule the final operation.

Asynchronous Data Download Procedural Break

Following up with the post: Can AFNetworking return data synchronously (inside a block)?
One of the comments in that post was:
The trick to asynchronous programming is to break the procedural,
synchronous assumption that data is there when you ask for it.
Instead, with async, when you ask for something, you give it a
callback to perform when the data finally is ready. In this case, you
would call the block in the success block of the JSON operation.
Rather than the method returning data, it's told what to do when the
data is finished downloaded.
Although I'm using GCD and asynchronous downloading on iOS, I do not really understand how to implement this "procedural break" when programming with async.
For example, assume I need to download some JSON data, which includes lots of data including an image URL. I will have to download the actual image afterwards.
Each cell in the table takes in the data from the JSON/images downloaded. How would I implement this procedural break in this case?
While your data has not arrived, your table view dataSource tells its table view that it has zero rows, and displays a spinner. When the callback is fired, you store the data somewhere, remove the spinner, and call [tableView reloadData]. Basically, that's all there is to it.

Resources